Отправка PDF-файлов пользователю из nodejs в reactjs

У меня есть pdf-документы, хранящиеся в файловой системе на стороне сервера.

Мне нужно, чтобы пользователь загружал один из них, когда он/она нажимает на загрузку.

Проблема в том, что я знаю, как отправить файл из NodeJS в браузер, но здесь запрос будет сделан запросом axios ReactJS. Поэтому, когда я отправляю файл, ответ будет реагировать. Как мне отправить этот PDF-файл пользователю? Имею ли я доступ к файловой системе напрямую, используя код переднего плана?

Я получаю следующее в консоли браузера, когда я регистрирую ответ после того, как я делаю res.sendFile(file_path) в NodeJS

Отправка PDF-файлов пользователю из nodejs в reactjs

Как мне обработать это, чтобы пользователь мог загрузить PDF-файл?

Вы используете обратный прокси-сервер, такой как Nginx, так как он оптимизирован для обмена статическими файлами?

mehta-rohan 06.06.2019 10:42

Нет, я не использую Nginx. На самом деле моя проблема заключается в том, чтобы каким-то образом разрешить пользователю загружать файл PDF, но, поскольку запрос должен быть сделан с помощью реакции, я не могу заставить его загрузить файл.

Abdul Ahad 06.06.2019 10:54

какова ваша конечная цель?

mehta-rohan 06.06.2019 10:55

Как только пользователь нажимает кнопку «Загрузить», он/она должен иметь возможность загрузить этот конкретный файл, хранящийся в моей файловой системе (какой бы метод я ни использовал). Это нормально, если я не вовлекаю в это серверную часть (я не уверен, что это правильно)?

Abdul Ahad 06.06.2019 10:56

должна быть опция для sendFile в ответ, или вы можете отправить данные обратно клиенту и сгенерировать pdf на стороне клиента

mehta-rohan 06.06.2019 11:01

Да, файл отправки работает, но что мне сделать, чтобы пользователь загрузил файл или как мне обработать его, как только я его получу.

Abdul Ahad 06.06.2019 11:21

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

mehta-rohan 06.06.2019 11:25

Именно это я и спрашиваю, я могу отправить файл с помощью res.sendFIle, после этого как мне его обработать? В заголовке написано: cache-control: "public, max-age=0" content-type: "application/pdf" last-modified: "Чт, 06 июня 2019 г., 07:10:57 по Гринвичу"

Abdul Ahad 06.06.2019 11:31
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
8
5 235
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать файл-сохранитель для загрузки файла. Ниже приведена функция, которую я использую для загрузки PDF. (response.data — это буфер, который nodejs отправляет обратно в качестве ответа)

import FileSaver from 'file-saver';
...

_onPdfFetched() {
  FileSaver.saveAs(
    new Blob([response.data], { type: 'application/pdf' }),
    `sample.pdf`
  );
}

или вы можете просто показать pdf пользователю

window.open(response.data, '_blank');

Редактировать

Вызов axios должен быть таким:

axios.get(url, {
  responseType: 'arraybuffer',
  headers: {
      Accept: 'application/pdf',
  },
});

Редактировать 2

Код nodejs должен быть таким:

router.post('/api/downloadfile',(req, res, next) => {
  const src = fs.createReadStream('path to sample.pdf');

  res.writeHead(200, {
    'Content-Type': 'application/pdf',
    'Content-Disposition': 'attachment; filename=sample.pdf',
    'Content-Transfer-Encoding': 'Binary'
  });

  src.pipe(res); 
});

Загрузка происходит, но содержимое pdf полностью искажено.

Abdul Ahad 06.06.2019 11:59

Я уже говорил вам, что response.data — это буфер, который nodejs отправляет обратно в качестве ответа. Вы должны отправить буфер из nodejs

Vasileios Pallas 06.06.2019 12:05

Я много искал, но так и не понял, как отправить файловый буфер из node. Я использовал file.pipe() и другие меры, но с тем же результатом. Есть ли какой-либо документ, на который я мог бы сослаться, или вы могли бы сказать мне, как именно буфер отправляется на стороне сервера.

Abdul Ahad 06.06.2019 12:30

Можете ли вы предоставить код nodejs, чтобы помочь вам?

Vasileios Pallas 06.06.2019 12:40
router.post('/api/downloadfile',(req,res,next)=>{ pathname=path.join(__dirname,'../../../documents','sample.pd‌​f'); res.sendFile(pathname); }) Я тоже пробовал, но безрезультатно: связь
Abdul Ahad 06.06.2019 12:47

если вы попытаетесь заменить res.sendFile(pathname) на res.attachment(pathname), это сработает? Поскольку этот добавляет правильные заголовки // Content-Disposition: attachment; filename = "file.pdf"// Content-Type: application/json или даже лучше, вы можете использовать res.download(pathname), который может сделать эту работу за вас.

Vasileios Pallas 06.06.2019 13:08

Я попробовал оба со следующим вызовом axios, но с тем же результатом: axios.post('http://localhost:7000/api/downloadfile',{ responseType: 'arraybuffer', headers: { Accept: 'application/pdf', },}) .then(res=>{ console.info("RESPONSE IS:",res); FileSaver.saveAs( new Blob([res.data], { type: 'application/pdf' }), name.pdf`); }) .catch(err=>{ console.info("ошибка",err); })`

Abdul Ahad 06.06.2019 13:18

Я редактирую свой ответ с кодом nodejs. Я надеюсь, что это поможет вам

Vasileios Pallas 06.06.2019 13:42

Пробовал, чувак, тот же результат. Даже с разными PDF-файлами содержимое полностью теряется. Я понятия не имею, что делать. Для черно-белых PDF-файлов я просто получаю пустые страницы.

Abdul Ahad 06.06.2019 14:21

Если вы попытаетесь запустить свою конечную точку на почтальоне, каков будет ответ?

Vasileios Pallas 06.06.2019 15:05

С почтальоном я получаю правильный pdf. Никакой потери данных. Мой внешний вызов: axios.post('http://localhost:7000/api/downloadfile',{ responseType: 'arraybuffer', headers: { Accept: 'application/pdf', },}) .then(res=>{ console.info("RESPONSE IS:",res); FileSaver.saveAs( new Blob([res.data], { type: 'application/pdf' }), name.pdf`); }) .catch(err=>{ console.info("ошибка",err); })`

Abdul Ahad 06.06.2019 15:57

возможно, ответ не нужно преобразовывать в Blob. Попробуйте просто передать данные ответа на File saver вот так: FileSaver.saveAs(response.data, 'sample.pdf');

Vasileios Pallas 06.06.2019 16:02

Нет, я получаю сообщение об ошибке: Не удалось выполнить «открыть» для «XMLHttpRequest»: неверный URL-адрес и похоже, что нужно использовать большой двоичный объект с файловой системой.

Abdul Ahad 06.06.2019 16:14

хорошо, я вижу, что происходит. Вы делаете axios.post, а не axios.get, что означает, что опции должны быть третьим параметром (при пост-вызове вторым параметром является тело запроса). Таким образом, это должно выглядеть так: axios.post(url, {}, { responseType: 'arraybuffer', headers: { Accept: 'application/pdf'}})

Vasileios Pallas 06.06.2019 16:53

сработало как шарм, большое спасибо. Так это было? Неверный список параметров? И не могли бы вы объяснить, что здесь происходит, я имею в виду, что мы конвертируем pdf в поток байтов, а затем обрабатываем его. В том, что все?

Abdul Ahad 06.06.2019 16:56

На самом деле я считаю, что проблема была в вызове axios. Теперь о коде nodejs, который я вам дал, он предназначен для лучшего использования файлов с использованием каналов. Вы можете увидеть эта статья

Vasileios Pallas 06.06.2019 17:36

Этот ответ заставил меня пройти долгий путь. Но по какой-то причине браузер неправильно открывает файл PDF. Мой вызов axios выглядит так: axios .get('SDS/openPDFFile', { params: { pdf }, responseType: 'arraybuffer', headers: { Accept: 'application/pdf' } }) .then((res) => { console.info(res); window.open(res.data, '_blank'); }); И тут браузер пытается открыть: http://localhost:3000/[object%20ArrayBuffer]

dmikester1 28.07.2020 18:23

@ dmikester1 Вы пытались преобразовать ответ в Blob?

Vasileios Pallas 30.07.2020 16:27

Я использую этот способ в Node Backend: res.setHeader("Content-Type", "application/pdf"); res.setHeader( "Content-Disposition", `attachment; filename= someFileName.pdf` ); res.end(data); Во внешнем интерфейсе, используя Axios: ``` axios.post("yourapi/blah/blah",{data: {somedata: somevalue},},{responseType:"arraybuffer",headers: {Accept: "application/pdf", }, } ) .then((result) => { FileDownload( new Blob([result.data], {type: "application/pdf" }), fileName); }) ` ``

rohitpaniker 17.08.2020 18:27

Я думаю, вам не хватает заголовка 'Content-Transfer-Encoding': 'Binary' в коде nodejs

Vasileios Pallas 17.08.2020 19:30

Другие вопросы по теме