Node.js Télécharger le fichier en utilisant le contenu Disposition comme nom de fichier

J’utilise le module Request pour télécharger des fichiers, mais je ne sais pas trop comment diriger la réponse vers un stream de sortie lorsque le nom du fichier doit provenir de l’en-tête ‘Content-Disposition’. Donc, fondamentalement, je dois lire la réponse jusqu’à ce que l’en-tête soit trouvé, puis diriger le rest vers ce nom de fichier.

Les exemples montrent quelque chose comme:

request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'));

Où je veux faire (pseudocode):

 var req = request('http://example.com/download_latest_version?token=XXX'); var filename = req.response.headers['Content-Disposition']; req.pipe(fs.createWriteStream(filename)); 

Je pourrais obtenir le nom du fichier en utilisant le rappel de requête:

 request(url, function(err, res, body) { // get res headers here }); 

Mais cela n’annule-t-il pas les avantages de l’utilisation de pipe et de ne pas charger le fichier téléchargé en mémoire?

Je demande une image de Yahoo et elle n’utilise pas l’ content-disposition tête content-disposition mais j’extrais les content-type têtes de content-type date et content-type pour créer un nom de fichier. Cela semble assez proche de ce que vous essayez de faire …

 var request = require('request'), fs = require('fs'); var url2 = 'http://soffr.miximages.com/request/aaroncarter_635x250_1385060042.jpg'; var r = request(url2); r.on('response', function (res) { res.pipe(fs.createWriteStream('./' + res.headers.date + '.' + res.headers['content-type'].split('/')[1])); }); 

Ignorer mon choix d’image s’il vous plaît 🙂

La question a été autour pendant un certain temps, mais j’ai aujourd’hui fait face au même problème et l’ai résolu différemment:

 var Request = require( 'request' ), Fs = require( 'fs' ); // RegExp to extract the filename from Content-Disposition var regexp = /filename=\"(.*)\"/gi; // initiate the download var req = Request.get( 'url.to/somewhere' ) .on( 'response', function( res ){ // extract filename var filename = regexp.exec( res.headers['content-disposition'] )[1]; // create file write stream var fws = Fs.createWriteStream( '/some/path/' + filename ); // setup piping res.pipe( fws ); res.on( 'end', function(){ // go on with processing }); }); 

Voici ma solution:

 var fs = require('fs'); var request = require('request'); var through2 = require('through2'); var req = request(url); req.on('error', function (e) { // Handle connection errors console.log(e); }); var bufferedResponse = req.pipe(through2(function (chunk, enc, callback) { this.push(chunk); callback() })); req.on('response', function (res) { if (res.statusCode === 200) { try { var contentDisposition = res.headers['content-disposition']; var match = contentDisposition && contentDisposition.match(/(filename=|filename\*='')(.*)$/); var filename = match && match[2] || 'default-filename.out'; var dest = fs.createWriteStream(filename); dest.on('error', function (e) { // Handle write errors console.log(e); }); dest.on('finish', function () { // The file has been downloaded console.log('Downloaded ' + filename); }); bufferedResponse.pipe(dest); } catch (e) { // Handle request errors console.log(e); } } else { // Handle HTTP server errors console.log(res.statusCode); } }); 

Les autres solutions publiées ici utilisent res.pipe , ce qui peut échouer si le contenu est transféré à l’aide du codage gzip , car le stream de réponse contient les données HTTP brutes (compressées). Pour éviter ce problème, vous devez utiliser request.pipe place. (Voir le second exemple à l’ adresse https://github.com/request/request#examples .)

Lors de l’utilisation de request.pipe un message d’erreur apparaissait: “Vous ne pouvez pas rediffuser après que les données aient été émises par la réponse.” J’ai également eu quelques problèmes où le fichier était écrit sans contenu, ce qui pouvait être dû à la request lecture de la réponse HTTP et à sa mise en mémoire tampon.

J’ai donc fini par créer un stream de mise en mémoire tampon intermédiaire avec through2 , afin de pouvoir y diriger la demande avant le déclenchement du gestionnaire de réponses, puis une mise en sortie ultérieure du stream de mise en mémoire tampon dans le stream de fichiers une fois le nom de fichier connu.

Enfin, j’parsing l’en-tête de disposition du contenu, que le nom du fichier soit codé en clair ou en UTF-8, à l’aide de la syntaxe filename*=''file.txt .

J’espère que cela aidera quelqu’un d’autre qui connaît les mêmes problèmes que moi.