2014-10-19 135 views
0

所以我試圖在Node.js中編寫一個基本的文件服務器,並且我嘗試上傳並存儲在其上的所有圖像都已經損壞。這個問題似乎與Node Buffers處理被轉換爲UTF-8並返回的方式有關(爲了使POST主體頭部遠離二進制數據,我必須這樣做)。Node.js服務器:圖像上傳/損壞問題

這裏有一個簡單的節點服務器,顯示我目前的做法,我一直有問題:

var http = require('http'); 

var server = http.createServer(function(request, response) { 
    if (request.method === "GET") { 
     // on GET request, output a simple web page with a file upload form 
     var mypage = '<!doctype html><html><head><meta charset="utf-8">' + 
         '<title>Submit POST Form</title></head>\r\n<body>' + 
         '<form action="http://127.0.0.1:8008" method="POST" ' + 
         'enctype="multipart/form-data"> <input name="upload" ' + 
         'type="file"><p><button type="submit">Submit</button>' + 
         '</p></form></body></html>\r\n'; 
     response.writeHead(200, { 
      "Content-Type": "text/html", 
      "Content-Length": mypage.length 
     }); 
     response.end(mypage); 

    } else if (request.method === "POST") { 
     // if we have a return post request, let's capture it 
     var upload = new Buffer([]); 

     // get the data 
     request.on('data', function(chunk) { 
      // copy post data 
      upload = Buffer.concat([upload, chunk]); 
     }); 

     // when we have all the data 
     request.on('end', function() { 
      // convert to UTF8 so we can pull out the post headers 
      var str = upload.toString('utf8'); 
      // get post headers with a regular expression 
      var re = /(\S+)\r\nContent-Disposition:\s*form-data;\s*name="\w+";\s*filename="[^"]*"\r\nContent-Type: (\S+)\r\n\r\n/i, 
       reMatch = str.match(re); 
      var lengthOfHeaders = reMatch[0].length, 
       boundary = reMatch[1], 
       mimeType = reMatch[2]; 
      // slice headers off top of post body 
      str = str.slice(lengthOfHeaders); 
      // remove the end boundary 
      str = str.replace("\r\n" + boundary + "--\r\n", ''); 
      // convert back to buffer 
      var rawdata = new Buffer(str, 'utf8'); 
      // echo back to client 
      response.writeHead(200, { 
       "Content-Type": mimeType 
      }); 
      response.end(rawdata); 
     }); 
    } 
}); 

server.listen(8008); 
console.log("server running on port 8008"); 

爲了測試它,在節點上運行腳本,然後轉到127.0.0.1:8008在您的瀏覽器。嘗試上傳圖片並提交表單。即使腳本應該直接將圖像數據回顯給瀏覽器,圖像每次都會損壞。

所以有人知道我在這裏做錯了嗎?有沒有更好的方法來處理Node中的POST body標題,我還沒有想出來? (和任何人說任何東西之前,不,我想用快遞,我想弄清楚,理解這個問題。)

回答

0

真的不應該使用正則表達式一樣,要多分析有效載荷,因爲它可以很容易地嘗試解析您的圖像數據非常不可靠。有npm上的模塊可以爲你解析表格,如busboymultipartyformidable。他們都沒有使用正則表達式,他們不需要Express。

+0

感謝您的建議。似乎在這種情況下,布斯博士可能會滿足我的需求。也就是說,我仍然想知道我在這裏做錯了什麼。除了使用您認爲可能導致它的正則表達式之外,還有其他什麼嗎? – 2014-10-19 23:20:32

+0

此外,剛剛註冊[問題](https://github.com/mscdex/busboy/issues/62)在busboy上。似乎沒有爲我工作。 – 2014-10-19 23:53:55

+0

你並沒有給busboy提供任何數據。在你的事件處理程序後添加'request.pipe(busboy);'。 – mscdex 2014-10-20 00:20:46

-1

我面臨完全一樣的問題,然後我碰到這篇文章是約二進制數據coverting爲utf8的危害......繼承人link

作者演示瞭如何它可能會破壞原始數據。我沒有嘗試過自己,它的確會改變圖像數據

0

這個問題似乎有些事情要與節點緩衝處理轉換爲UTF-8,然後再返回

我猜的方式你是對的,轉換爲UTF-8是一個壞主意,但可以做到這一點,只是爲了處理文件,並獲得標題和邊界位置,但保持緩衝區文件不變,並且當你有所有的位置獲得文件的標題和邊界只是將緩衝區複製到一個新的緩衝區,就像那樣

originalBuffer.copy(new Buffer,0,positionHeader,positionEndBoundary)

var http = require('http'); 
var fs = require('fs'); 
var connections = 0; 

var server = http.createServer(function (req, res) { 
connections++; 
console.log(req.url,"connections: "+connections); 
if(req.url == '/'){ 
    res.writeHead(200, { 'content-type': 'text/html' }); 
    res.end(
     '<form action="/upload" enctype="multipart/form-data" method="post">' + 
     '<input type="file" name="upload" multiple="multiple"><br>' + 
     '<input type="submit" value="Upload">' + 
     '</form>' 
    ); 
} 

var body = new Buffer([]); 
if (req.url == '/upload') { 
    req.on('data', function (foo) { 

     //f.write(foo); 
     body = Buffer.concat([body,foo]); 
     if(isImage(body.toString())){ 
      console.log("é imagem do tipo "+isImage(body.toString())); 
     } 
     else{ 
      console.log("Não é imagem"); 
      res.end("Não é imagem"); 
     } 
     console.log(body.length, body.toString().length); 
    }); 
    req.on('end', function() { 
     // console.log(req.headers); 
     //I converted the buffer to "utf 8" but i kept the original buffer 
     var str = body.toString(); 
     console.log(str.length); 
     imageType = isImage(body.toString()); 
     //get the index of the last header character 
     //I'm just using the string to find the postions to cut the headers and boundaries 
     var index = str.indexOf(imageType)+(imageType+"\r\n\r\n").length; 
     // var headers= str.slice(0,index).split(';'); 
     // console.log(headers); 

     //Here comes the trick 
     /* 
     *I have to cut the last boundaries, so i use the lastIndexOf to cut the second boundary 
     * And maybe that is the corruption issues, because, I'm not sure, but I guess 
     * the UTF-8 format only use 7bits to represent all characters, and the buffer can use 8bits, or two hex, 
     *So, i need to take the difference here (body.length-str.length) 
     */ 
     var indexBoundayToBuffer = str.lastIndexOf('------WebKitFormBoundary')+(body.length-str.length); 
     console.log(index, indexBoundayToBuffer); 
     //maybe you can change this to use less memory, whatever 
     var newBuffer = Buffer.alloc(body.length); 
     /* 
     *And now use the index, and the indexBoudayToBuffer and you will have only the binary 
     */ 
     body.copy(newBuffer,0,index,indexBoundayToBuffer); 

     // f.end(); 
     //file type 
     var type = imageType.substr("image/".length); 
     console.log("END"); 
     fs.writeFile("nameFile."+type,newBuffer,function(err,ok){ 
      if(err){ 
       console.log(err); 
       return false; 
      } 
      res.end(); 

     }); 
    }); 
} 

}); 

function isImage(str){ 

if(str.indexOf('image/png')!=-1) return 'image/png'; 
else if(str.indexOf('image/jpeg')!=-1) return 'image/jpeg'; 
else if(str.indexOf('image/bmp'!=-1)) return 'image/bmp'; 
else if(str.indexOf('image/gif'!=-1)) return 'image/gif'; 
else false; 
} 

var port = process.env.PORT || 8080; 
server.listen(port, function() { 
console.log('Recording connections on port %s', port); 
});