web-dev-qa-db-fra.com

Node Express.js - Télécharger le fichier depuis la mémoire - 'le nom de fichier doit être une chaîne'

J'essaie de regrouper les données en mémoire dans un fichier texte et de les envoyer à l'utilisateur, déclenchant un téléchargement de fichier.

J'ai le code suivant:

app.get('/download', function(request, response){

    fileType = request.query.fileType;
    fileName = ( request.query.fileName + '.' + fileType ).toString();
    fileData = request.query.fileData;

    response.set('Content-disposition', 'attachment; filename=' + fileName );
    response.set('Content-type', 'text/plain');

    var fileContents = new Buffer(fileData, "base64");

    response.status(200).download( fileContents );

});

Il continue de générer une erreur indiquant que le paramètre de nom de fichier de Content-disposition doit être une chaîne. fileName est très certainement une chaîne, donc je ne suis pas sûr de ce qui se passe.

10
Karric

Mise à jour:

Grâce aux conseils de @ jfriend00, il est préférable et plus efficace d'envoyer directement le tampon au client sous forme de fichier, au lieu de l'enregistrer d'abord sur le disque du serveur.

Pour l'implémentation, stream.PassThrough() et pipe() peuvent être utilisés, voici un exemple:

var stream = require('stream');
//...
app.get('/download', function(request, response){
  //...
  var fileContents = Buffer.from(fileData, "base64");

  var readStream = new stream.PassThrough();
  readStream.end(fileContents);

  response.set('Content-disposition', 'attachment; filename=' + fileName);
  response.set('Content-Type', 'text/plain');

  readStream.pipe(res);
});

Selon Express document , res.download() API est:

res.download (chemin [ nom de fichier] [ fn])

Transfère le fichier au chemin en tant que "pièce jointe". En règle générale, les navigateurs invitent l'utilisateur à télécharger. Par défaut, le paramètre "filename =" de l'en-tête Content-Disposition est chemin (cela apparaît généralement dans la boîte de dialogue du navigateur). Remplacez cette valeur par défaut par le paramètre filename.

Veuillez noter que le premier paramètre de res.download() est un "chemin", qui indique le chemin du fichier sur le serveur qui serait téléchargé. Dans votre code, le premier paramètre est un tampon, c'est pourquoi Node.js se plaint que "le paramètre de nom de fichier doit être une chaîne" - Par défaut, le paramètre d'en-tête Content-Disposition "Filename =" est path .

Pour faire fonctionner votre code à l'aide de res.download(), vous devez enregistrer le fileData dans le serveur en tant que fichier, puis appeler res.download() avec le chemin d'accès de ce fichier:

var fs = require('fs');
//...
app.get('/download', function(request, response){
  //...
  var fileContents = Buffer.from(fileData, "base64");
  var savedFilePath = '/temp/' + fileName; // in some convenient temporary file folder
  fs.writeFile(savedFilePath, fileContents, function() {
    response.status(200).download(savedFilePath, fileName);
  });
});

Notez également que new Buffer(string[, encoding]) est désormais obsolète. Il vaut mieux utiliser Buffer.from(string[, encoding]).

20
shaochuancs