Подтвердить что ты не робот

Загруженные файлы .pdf повреждены при использовании expressjs

Я работаю над приложением meanjs, сгенерированным с помощью https://github.com/DaftMonk/generator-angular-fullstack. Я пытаюсь сгенерировать файл .pdf с помощью phantomjs и загрузить его в браузер.

Проблема заключается в том, что загруженный .pdf файл всегда показывает пустые страницы независимо от количества страниц. Исходный файл на сервере не поврежден. Когда я исследовал дальше, обнаружил, что загруженный файл всегда намного больше, чем исходный файл на диске. Также эта проблема возникает только с .pdf файлами. Другие типы файлов работают нормально.

Я пробовал несколько методов, таких как 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);

и даже я пробовал с https://github.com/expressjs/serve-static без изменений в результате.

Я новичок в nodejs. Каков наилучший способ загрузки PDF файла в браузер?

Update: Я запускаю это на 64-битном компьютере Windows 8.1.

4b9b3361

Ответ 1

Вот простой способ обслуживать файл из express и использует заголовок attachment, чтобы убедиться, что файл загружен:

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

Ответ 2

У меня была коррупция при обслуживании статических PDF файлов. Я попробовал все, что было предложено выше. Тогда я нашел это: https://github.com/intesso/connect-livereload/issues/39 В сущности, обычно превосходная связь-livereload (пакет ~ 0.4.0) искажала pdf. Поэтому просто попробуйте проигнорировать pdf файлы через:

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

теперь это работает:

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

... большое облегчение.

Ответ 3

Обычно, если вы используете phantom для создания pdf файла, тогда файл будет записан на диск, и вы должны указать путь и обратный вызов для функции рендеринга.

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

Ответ 4

Есть несколько способов сделать это:

  • Если файл является статическим, например брошюрой, readme и т.д., то вы можете сказать, что моя папка имеет статические файлы (и должна быть доступна напрямую) и сохранить там файл. Это делается с использованием статического промежуточного программного обеспечения: app.use(express.static(pathtofile)); Вот ссылка: http://expressjs.com/starter/static-files.html

Теперь вы можете напрямую открыть файл, используя URL-адрес браузера, например:

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

или

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

должен работать.

  1. Второй способ - прочитать файл, данные должны поступать в виде буфера. Фактически, это должно быть распознано, если вы отправляете его напрямую, но вы можете попробовать преобразовать его в кодировку base64, используя:

    var base64String = buf.toString('base64');

затем установите тип содержимого:

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

и отправить данные как ответ. Я попытаюсь привести пример этого.

EDIT: вам даже не нужно его кодировать. Вы можете попробовать это еще. Но я смог заставить его работать, даже не кодируя его.

Кроме того, вам также не нужно устанавливать заголовки. Экспресс делает это за вас. Ниже приведен фрагмент кода API, написанный для получения pdf файла, если он не является общедоступным/статическим. Вам нужен API для обслуживания pdf:

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

Наконец, обратите внимание, что URL-адрес для получения pdf имеет расширение pdf для него, это значит, что браузер распознает, что входящий файл является pdf. В противном случае он сохранит файл без расширения.

Ответ 5

У меня нет опыта в тех фреймворках, которые вы упомянули, но я бы рекомендовал использовать такой инструмент, как Fiddler, чтобы посмотреть, что происходит. Например, вам может не понадобиться добавлять заголовок длины содержимого, поскольку вы выполняете потоковое вещание, а ваша фреймворк блокирует передачу и т.д.