英文:
Not able to download pdf-file (stored in binary data format) from Mongo-db using React JS
问题
I used express-fileupload to upload the PDF file to MongoDB. I am encountering a problem when trying to download that PDF file on the front end.
I'm receiving this error prompt after downloading the PDF: "Error. Failed to load PDF document".
FormData on MongoDB:
_id: ObjectId('63b7494295b850d0452a6a81')
username: "sita"
email: "sita@gmail.com"
dob: 2023-01-01T00:00:00.000+00:00
city: "city"
address: "add"
services: Array
0: "Demat"
pancard: Object
Data: BinData(0,'JVBERi0xLjcKCjQgMCBvYmoKPDwKL0ZpbHRlciAvRmxhdGVEZWNvZGUKL0xlbmd0aCAzMDEzNQo+PgpzdHJlYW0KeJztvU1247gS…')
ContentType: "application/pdf"
createdAt: 2023-01-05T22:03:46.893+00:00
updatedAt: 2023-01-05T22:03:46.893+00:00
__v: 0
[ReactJS code:]
React.useEffect(() => {
const fetchClient = async () => {
const res = await axios.get('/users/sita@gmail.com');
setData(res.data.pancard.Data.data);
setContentType(res.data.pancard.contentType);
}
fetchClient();
}, [userdetail]);
const downloadPdf = (filename, contentType) => {
const file = new Blob([data], { type: contentType });
saveAs(file, "pancard.pdf");
// const fileURL = URL.createObjectURL(file);
// window.open(fileURL);
};
Calling downloadPdf()
method here in JSX:
<button class="btn btn-primary button" onClick={downloadPdf('pancard', contentType)}>Download</button>
The file is also getting downloaded infinitely in a loop.
英文:
I used express-fileuplod for uploading the pdf file on Mongodb. I am facing problem to download that pdf file on front end.
I'm getting this prompt after downloading the pdf: "Error. Failed to load PDF document"
form-data on MongoDB:
_id: ObjectId('63b7494295b850d0452a6a81')
username: "sita"
email: "sita@gmail.com"
dob: 2023-01-01T00:00:00.000+00:00
city: "city"
address: "add"
services: Array
0: "Demat"
pancard: Object
Data:BinData(0,'JVBERi0xLjcKCjQgMCBvYmoKPDwKL0ZpbHRlciAvRmxhdGVEZWNvZGUKL0xlbmd0aCAzMDEzNQo+PgpzdHJlYW0KeJztvU1247gS…')
ContentType: "application/pdf"
createdAt: 2023-01-05T22:03:46.893+00:00
updatedAt: 2023-01-05T22:03:46.893+00:00
__v: 0
[reactjs code:]
React.useEffect(()=>{
const fetchClient = async () =>{
const res = await axios.get('/users/sita@gmail.com');
setData(res.data.pancard.Data.data);
setContentType(res.data.pancard.contentType)
}
fetchClient()
},[userdetail]);
const downloadPdf = (filename, contentType) => {
const file = new Blob([data], { type: contentType });
saveAs(file, "pancard.pdf")
//const fileURL = URL.createObjectURL(file);
//window.open(fileURL);
};
Calling downloadpdf() method here in JSX
> <button class="btn btn-primary button" onClick={downloadPdf('pancard', contentType)}>Download</button>
The file is also getting downloaded infinite times in loop
答案1
得分: 1
Solution 1
那个 data
只是一个数组,我们需要将其转换为 Uint8Array
const file = new Blob([new Uint8Array(data)], { type: contentType });
saveAs(file, "pancard.pdf")
Solution 2
我们必须在另一个路由上提供文件,不能与 JSON 数据一起发送
后端
// 在 Express 中的示例
app.get('/get_file', (req, res) => {
// 查询用户
res.set('Content-Disposition', 'attachment; filename="test.pdf"');
res.set('Content-Type', 'application/pdf');
res.send(user.pancard);
}
前端
fetch('http://localhost:8000/get_file')
.then(res => res.blob())
.then(data => {
saveAs(data, 'test.pdf');
})
对于大文件,Solution 2 更好,因为它使用了 Content-Disposition
标头,可以安全地传输文件数据(我不太了解其底层机制,请进一步研究)
还请注意两件事情:
- 不建议将文件数据直接保存到数据库中。而是将其保存为静态文件,只将路径存储到数据库中。
- 如果文件大小超过 16mb,则需要使用 Mongo 的 GridFS。更多详情:https://www.mongodb.com/docs/manual/core/gridfs/
英文:
Solution 1
That data
is only an Array, we need to convert to Uint8Array
const file = new Blob([new Uint8Array(data)], { type: contentType });
saveAs(file, "pancard.pdf")
Solution 2
We have to serve file on another route, it can not be sent with json data
backend
// Example in Express
app.get('/get_file', (req, res) => {
// Query user
res.set('Content-Disposition', 'attachment; filename="test.pdf"');
res.set('Content-Type', 'application/pdf');
res.send(user.pancard);
}
frontend
fetch('http://localhost:8000/get_file')
.then(res => res.blob())
.then(data => {
saveAs(data, 'test.pdf');
})
With large file, Solution 2 is better thanks to the Content-Disposition
header. File data is transferred safely with this header (I don't really understand the underlying mechanism, please research further)
Also notice 2 things:
- It is not recommend to save file data directly into database. Instead, save as static file and only store the path to database.
- If file size exceed 16mb. We need to use GridFS for Mongo. More details: https://www.mongodb.com/docs/manual/core/gridfs/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论