Les fichiers .pdf téléchargés sont corrompus lors de l’utilisation de expressjs

Je travaille sur l’application meanjs générée à l’aide de https://github.com/DaftMonk/generator-angular-fullstack . J’essaie de générer un fichier .pdf à l’aide de phantomjs et de le télécharger sur le navigateur.

Le problème est que le fichier .pdf téléchargé affiche toujours les pages vierges, quel que soit le nombre de pages. Le fichier d’origine sur le serveur n’est pas corrompu. Lorsque j’ai étudié plus en profondeur, j’ai constaté que le fichier téléchargé était toujours beaucoup plus volumineux que le fichier d’origine sur le disque. De plus, ce problème se produit uniquement avec les fichiers .pdf. Les autres types de fichiers fonctionnent bien.

J’ai essayé plusieurs méthodes telles que res.redirect('http://localhost:9000/assets/exports/receipt.pdf'); , res.download('client\\assets\\exports\\receipt.pdf') ,

 var fileSystem = require('fs'); var stat = fileSystem.statSync('client\\assets\\exports\\receipt.pdf'); res.writeHead(200, { 'Content-Type': 'application/pdf', 'Content-Length': stat.size }); var readStream = fileSystem.createReadStream('client\\assets\\exports\\receipt.pdf'); return readStream.pipe(res); 

et même j’ai essayé avec https://github.com/expressjs/serve-static sans modifier le résultat.

Je suis nouveau sur nodejs . Quel est le meilleur moyen de télécharger un fichier .pdf sur le navigateur?

Mise à jour: j’utilise cette application sur un ordinateur Windows 8.1 64 bits

Voici un moyen propre de servir un fichier express, et utilise un en-tête de attachment pour s’assurer que le fichier est téléchargé:

 var path = require('path'); var mime = require('mime'); app.get('/download', function(req, res){ //Here do whatever you need to get your file var filename = path.basename(file); var mimetype = mime.lookup(file); res.setHeader('Content-disposition', 'attachment; filename=' + filename); res.setHeader('Content-type', mimetype); var filestream = fs.createReadStream(file); filestream.pipe(res); }); 

J’ai eu la corruption en servant des fichiers PDF statiques aussi. J’ai essayé tout ce qui est suggéré ci-dessus. Ensuite, j’ai trouvé ceci: https://github.com/intesso/connect-livereload/issues/39 En substance, l’excellent connect-livereload (paquet ~ 0.4.0) corrompait le pdf. Alors faites-le savoir pour ignorer les fichiers PDF via:

 app.use(require('connect-livereload')({ignore: ['.pdf']})); 

maintenant cela fonctionne:

 app.use('/pdf', express.static(path.join(config.root, 'content/files'))); 

… grand soulagement.

Habituellement, si vous utilisez fantôme pour générer un fichier PDF, le fichier est alors écrit sur le disque et vous devez fournir le chemin d’access et un rappel à la fonction de rendu.

 router.get('/pdf', function(req, res){ // phantom initialization and generation logic // supposing you have the generation code above page.render(filePath, function (err) { var filename = 'myFile.pdf'; res.setHeader('Content-type', "application/pdf"); fs.readFile(filePath, function (err, data) { // if the file was readed to buffer without errors you can delete it to save space if (err) throw err; fs.unlink(filePath); // send the file contents res.send(data); }); }); }); 

Il y a plusieurs façons de faire ça:

  1. Si le fichier est statique, comme une brochure, un fichier Lisez-moi, etc., vous pouvez indiquer que mon dossier contient des fichiers statiques (et doit être disponible directement) et conserve le fichier à cet emplacement. Ceci est fait en utilisant un middleware statique: app.use (express.static (pathtofile)); Voici le lien: http://expressjs.com/starter/static-files.html

Maintenant, vous pouvez ouvrir directement le fichier en utilisant l’URL du navigateur comme:

 window.open('http://localhost:9000/assets/exports/receipt.pdf'); 

ou

 res.redirect('http://localhost:9000/assets/exports/receipt.pdf'); 

devrait fonctionner.

  1. La deuxième façon est de lire le fichier, les données doivent venir comme un tampon. En fait, il devrait être reconnu si vous l’envoyez directement, mais vous pouvez essayer de le convertir en encodage base64 en utilisant:

    var base64Ssortingng = buf.toSsortingng (‘base64’);

puis définissez le type de contenu:

 res.writeHead(200, { 'Content-Type': 'application/pdf', 'Content-Length': stat.size }); 

et envoyer les données en réponse. Je vais essayer de mettre un exemple de cela.

EDIT: Vous n’avez même pas besoin de l’encoder. Vous pouvez essayer ça encore. Mais j’ai pu le faire fonctionner sans même l’encoder.

De plus, vous n’avez pas non plus besoin de définir les en-têtes. Express le fait pour vous. Voici l’extrait de code d’API écrit pour obtenir le pdf au cas où il ne serait pas public / statique. Vous avez besoin d’une API pour servir le pdf:

 router.get('/viz.pdf', function(req, res){ require('fs').readFile('viz.pdf', function(err, data){ res.send(data); }) }); 

Enfin, notez que l’URL pour obtenir le pdf a une extension pdf, c’est pour que le navigateur reconnaisse que le fichier entrant est au format pdf. Sinon, le fichier sera sauvegardé sans aucune extension.

Je n’ai pas l’expérience des frameworks que vous avez mentionnés mais je recommanderais d’utiliser un outil tel que Fiddler pour voir ce qui se passe. Par exemple, vous n’aurez peut-être pas besoin d’append un en-tête de contenu puisque vous diffusez en continu et que votre infrastructure effectue l’encodage de transfert en bloc, etc.