首頁  >  文章  >  web前端  >  使用Node層如何實作multipart表單檔案上傳

使用Node層如何實作multipart表單檔案上傳

亚连
亚连原創
2018-06-14 11:48:171427瀏覽

下面我就為大家分享一篇Node層模擬實作multipart表單的檔案上傳範例,具有很好的參考價值,希望對大家有幫助。

有時候就是有這樣的需求,Nodejs做webserver,從瀏覽器端上傳檔案到後端伺服器,Node層只是做一個資料中轉,如果在這個過程中,Node webserver需要對資料進行適當加工,然後再Post到後端,那麼就得在Node層模擬檔上傳了。

首先,透過瀏覽器上傳文件,PostData格式是長著個樣子的:

#螢幕快照2014 -11-22 下午9.18.45.png

如圖,每一組資料其實就是用「-----WebkitFormBoundary.....」分隔開的,最後再用這個分隔符號結束,而且,這個分隔符號完全是可自訂的。

每一段提交數據,則透過Content-Disposition來描述,未指定Content-Type,則預設text/plain,如果是上傳的二進位文件,指定其mime-type即可。

簡單封裝一個方法,實作Node層的檔案上傳:

/**
 * 上传文件
 * @param files  经过formidable处理过的文件
 * @param req  httpRequest对象
 * @param postData 额外提交的数据
 */
function uploadFile(files, req, postData) {
 var boundaryKey = Math.random().toString(16);
 var endData = '\r\n----' + boundaryKey + '--';
 var filesLength = 0, content;

 // 初始数据,把post过来的数据都携带上去
 content = (function (obj) {
  var rslt = [];
  Object.keys(obj).forEach(function (key) {
   arr = ['\r\n----' + boundaryKey + '\r\n'];
   arr.push('Content-Disposition: form-data; name="' + key + '"\r\n\r\n');
   arr.push(obj[key]);
   rslt.push(arr.join(''));
  });
  return rslt.join('');
 })(postData);

 // 组装数据
 Object.keys(files).forEach(function (key) {
  if (!files.hasOwnProperty(key)) {
   delete files.key;
   return;
  }
  content += '\r\n----' + boundaryKey + '\r\n' +
   'Content-Type: application/octet-stream\r\n' +
   'Content-Disposition: form-data; name="' + key + '"; ' +
   'filename="' + files[key].name + '"; \r\n' +
   'Content-Transfer-Encoding: binary\r\n\r\n';
  files[key].contentBinary = new Buffer(content, 'utf-8');
  filesLength += files[key].contentBinary.length + fs.statSync(files[key].path).size;
 });

 req.setHeader('Content-Type', 'multipart/form-data; boundary=--' + boundaryKey);
 req.setHeader('Content-Length', filesLength + Buffer.byteLength(endData));

 // 执行上传
 var allFiles = Object.keys(files);
 var fileNum = allFiles.length;
 var uploadedCount = 0;
 allFiles.forEach(function (key) {
  req.write(files[key].contentBinary);
  var fileStream = fs.createReadStream(files[key].path, {bufferSize: 4 * 1024});
  fileStream.on('end', function () {
   // 上传成功一个文件之后,把临时文件删了
   fs.unlink(files[key].path);
   uploadedCount++;
   if (uploadedCount == fileNum) {
    // 如果已经是最后一个文件,那就正常结束
    req.end(endData);
   }
  });
  fileStream.pipe(req, {end: false});
 });
}

想法就這樣,程式碼也不複雜,可能額外需要注意的是,在http.request的response處理中,response.headers可能是gzip的,這時候buffer不能直接toString,需要透過zlib解碼再轉換成string,大概思路:

var result = [];
response.on('data', function (chunk) {
 result.push(chunk);
});

// 处理response
var _dealResponse = function (data) {
 var buffer = data;
 try {
  data = data.toString('utf8');
  data = data ? (JSON.parse(data) || data) : false;
 } catch (err) {
  // 接口返回数据格式异常,解析失败
  console.log(err);
 }

 self.res.writeHead(response.statusCode, 'OK', {
  'content-type': 'text/plain; charset=utf-8',
  'content-length': buffer.length
 });
 self.res.write(buffer);
 self.res.end();
};

response.on('end', function () {
 result = Buffer.concat(result);
 // gzip 的数据,需要zlib解码
 if (response.headers['content-encoding'] == 'gzip') {
  zlib.gunzip(result, function (err, dezipped) {
   var data = err ? new Buffer('{}') : dezipped;
   _dealResponse(data);
  });
 } else {
  _dealResponse(result);
 }
});

Mark一下,也許你經過正好需要~~~

上面是我整理給大家的,希望今後會對大家有幫助。

相關文章:

在HTTP中gzip壓縮問題

如何使用JS程式碼寫出貪吃蛇遊戲(詳細教學)

在Javascript中如何將路徑轉換為base64編碼

#

以上是使用Node層如何實作multipart表單檔案上傳的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn