Maison  >  Article  >  interface Web  >  Explication détaillée de la simulation de couche de nœuds pour implémenter le téléchargement de fichiers de formulaire en plusieurs parties

Explication détaillée de la simulation de couche de nœuds pour implémenter le téléchargement de fichiers de formulaire en plusieurs parties

小云云
小云云original
2018-01-03 09:29:431847parcourir

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 un transfert de données que si, au cours de ce processus, le serveur Web Node doit traiter les données. données de manière appropriée, puis publiez-les sur le backend, puis vous devez simuler le téléchargement de fichiers au niveau de la couche Node. Cet article partage principalement 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. Suivons l'éditeur et jetons un œil. J'espère que cela pourra aider tout le monde.

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

Capture d'écran 22/11/2014 21h18/45 png<.>

Comme le montre la figure, chaque ensemble de données est en fait séparé par "-----WebkitFormBoundary....", et se termine finalement par ce délimiteur, 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.

Encapsulez 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, et le code n'est pas compliqué. Ce à quoi vous devrez peut-être prêter une attention particulière, c'est au. traitement de la réponse de http.request , Response.headers peut être gzip Pour le moment, le tampon ne peut pas être directement toString. Il doit être décodé par zlib puis converti en chaîne. 🎜>Marquez-le. Peut-être que vous en aurez besoin lors de votre passage~~~

Recommandations associées :
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);
 }
});

Le rôle de enctype="multipart/form-data" dans le balise form pour télécharger des images sous la forme

classe de requête HTTP php, prend en charge GET, POST, Multipart/form-data

Pourquoi le le formulaire de téléchargement de fichiers doit être défini enctype="multipart/form-data"

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