Maison  >  Article  >  interface Web  >  Comment implémenter le téléchargement de fichiers de formulaire en plusieurs parties à l'aide de la couche Node

Comment implémenter le téléchargement de fichiers de formulaire en plusieurs parties à l'aide de la couche Node

亚连
亚连original
2018-06-14 11:48:171472parcourir

Maintenant, je vais partager avec vous un exemple de téléchargement de fichier de simulation de couche de nœuds pour implémenter un formulaire en plusieurs parties. Il a une bonne valeur de référence et j'espère qu'il sera utile à tout le monde.

Parfois, une telle demande existe. Nodejs est utilisé comme serveur Web pour télécharger des fichiers du navigateur vers le serveur back-end. La couche Node n'effectue qu'un transfert de données si, dans ce processus, le serveur Web Node a besoin. pour traiter correctement les données, puis les publier sur le backend, vous devez alors simuler le téléchargement de fichiers au niveau de la couche Node.

Tout d'abord, téléchargez le fichier via le navigateur. Le format PostData ressemble à ceci :

Capture d'écran 2014 -11. -22 PM 9.18.45.png

Comme le montre l'image, chaque ensemble de données est en fait séparé par "-----WebkitFormBoundary....", et finalement utilisé Ce délimiteur se termine , et ce délimiteur est entièrement personnalisable.

Chaque élément de données soumis est décrit par Content-Disposition. Si Content-Type n'est pas spécifié, la valeur par défaut est text/plain. S'il s'agit d'un fichier binaire téléchargé, spécifiez simplement son type MIME.

Encapsuler simplement une méthode pour implémenter le téléchargement de fichiers au niveau de la couche 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});
 });
}

C'est l'idée, le code n'est pas compliqué, et il peut y avoir des éléments supplémentaires. Il convient de noter que lors du traitement de la réponse de http.request, les réponse.headers peuvent être gzip. À ce stade, le tampon ne peut pas être directement toString et doit être décodé par zlib puis converti en chaîne. idée :

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);
 }
});

Marquez-le, peut-être que vous en aurez juste besoin en passant par là~~~

Ce qui précède est ce que j'ai compilé pour tout le monde, j'espère qu'il sera utile à tout le monde dans le monde. avenir.

Articles associés :

Problèmes de compression Gzip en HTTP

Comment écrire un jeu Snake en utilisant le code JS (tutoriel détaillé)

Comment convertir le chemin en encodage base64 en Javascript

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn