У меня есть pdf-документы, хранящиеся в файловой системе на стороне сервера.
Мне нужно, чтобы пользователь загружал один из них, когда он/она нажимает на загрузку.
Проблема в том, что я знаю, как отправить файл из NodeJS в браузер, но здесь запрос будет сделан запросом axios ReactJS. Поэтому, когда я отправляю файл, ответ будет реагировать. Как мне отправить этот PDF-файл пользователю? Имею ли я доступ к файловой системе напрямую, используя код переднего плана?
Я получаю следующее в консоли браузера, когда я регистрирую ответ после того, как я делаю res.sendFile(file_path) в NodeJS
Как мне обработать это, чтобы пользователь мог загрузить PDF-файл?
Нет, я не использую Nginx. На самом деле моя проблема заключается в том, чтобы каким-то образом разрешить пользователю загружать файл PDF, но, поскольку запрос должен быть сделан с помощью реакции, я не могу заставить его загрузить файл.
какова ваша конечная цель?
Как только пользователь нажимает кнопку «Загрузить», он/она должен иметь возможность загрузить этот конкретный файл, хранящийся в моей файловой системе (какой бы метод я ни использовал). Это нормально, если я не вовлекаю в это серверную часть (я не уверен, что это правильно)?
должна быть опция для sendFile в ответ, или вы можете отправить данные обратно клиенту и сгенерировать pdf на стороне клиента
Да, файл отправки работает, но что мне сделать, чтобы пользователь загрузил файл или как мне обработать его, как только я его получу.
после получения файла вы можете отображать файл PDF в своем браузере... если файл возвращается в байтах, вы должны преобразовать его в читаемый браузером файл.
Именно это я и спрашиваю, я могу отправить файл с помощью res.sendFIle, после этого как мне его обработать? В заголовке написано: cache-control: "public, max-age=0" content-type: "application/pdf" last-modified: "Чт, 06 июня 2019 г., 07:10:57 по Гринвичу"





Вы можете использовать файл-сохранитель для загрузки файла. Ниже приведена функция, которую я использую для загрузки 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 полностью искажено.
Я уже говорил вам, что response.data — это буфер, который nodejs отправляет обратно в качестве ответа. Вы должны отправить буфер из nodejs
Я много искал, но так и не понял, как отправить файловый буфер из node. Я использовал file.pipe() и другие меры, но с тем же результатом. Есть ли какой-либо документ, на который я мог бы сослаться, или вы могли бы сказать мне, как именно буфер отправляется на стороне сервера.
Можете ли вы предоставить код nodejs, чтобы помочь вам?
router.post('/api/downloadfile',(req,res,next)=>{ pathname=path.join(__dirname,'../../../documents','sample.pdf'); res.sendFile(pathname); }) Я тоже пробовал, но безрезультатно: связьесли вы попытаетесь заменить res.sendFile(pathname) на res.attachment(pathname), это сработает? Поскольку этот добавляет правильные заголовки // Content-Disposition: attachment; filename = "file.pdf"// Content-Type: application/json или даже лучше, вы можете использовать res.download(pathname), который может сделать эту работу за вас.
Я попробовал оба со следующим вызовом 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); })`
Я редактирую свой ответ с кодом nodejs. Я надеюсь, что это поможет вам
Пробовал, чувак, тот же результат. Даже с разными PDF-файлами содержимое полностью теряется. Я понятия не имею, что делать. Для черно-белых PDF-файлов я просто получаю пустые страницы.
Если вы попытаетесь запустить свою конечную точку на почтальоне, каков будет ответ?
С почтальоном я получаю правильный 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); })`
возможно, ответ не нужно преобразовывать в Blob. Попробуйте просто передать данные ответа на File saver вот так: FileSaver.saveAs(response.data, 'sample.pdf');
Нет, я получаю сообщение об ошибке: Не удалось выполнить «открыть» для «XMLHttpRequest»: неверный URL-адрес и похоже, что нужно использовать большой двоичный объект с файловой системой.
хорошо, я вижу, что происходит. Вы делаете axios.post, а не axios.get, что означает, что опции должны быть третьим параметром (при пост-вызове вторым параметром является тело запроса). Таким образом, это должно выглядеть так: axios.post(url, {}, { responseType: 'arraybuffer', headers: { Accept: 'application/pdf'}})
сработало как шарм, большое спасибо. Так это было? Неверный список параметров? И не могли бы вы объяснить, что здесь происходит, я имею в виду, что мы конвертируем pdf в поток байтов, а затем обрабатываем его. В том, что все?
На самом деле я считаю, что проблема была в вызове axios. Теперь о коде nodejs, который я вам дал, он предназначен для лучшего использования файлов с использованием каналов. Вы можете увидеть эта статья
Этот ответ заставил меня пройти долгий путь. Но по какой-то причине браузер неправильно открывает файл 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 Вы пытались преобразовать ответ в Blob?
Я использую этот способ в 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); }) ` ``
Я думаю, вам не хватает заголовка 'Content-Transfer-Encoding': 'Binary' в коде nodejs
Вы используете обратный прокси-сервер, такой как Nginx, так как он оптимизирован для обмена статическими файлами?