javascript - Express.JS response.download 不下载文件
问题描述
我正在使用 Express 根据用户输入生成和下载 PDF 的 Node.JS 服务器。我使用 Axios POST 调用服务器,然后期望使用 Express 的 response.download() 下载文件。我最近从使用<form action="">
调用我的 API 的方法改为使用 Axios,因为 Netlify 似乎不支持 NuxtAPI。该程序在旧版本中生成了所需的文件,但是对 Axios 的更改意味着它不再有效。
现在,没有文件被下载(即使是固定路径的文件,例如在已发布的网站上),并且在提示下载之前页面正在重新加载。
我的代码如下:
打印.vue:
<template>
<main>
<button class="btn btn-primary" @click="submit">Print Certificate</button>
</main>
</template>
<script>
export default{
methods:{
async submit(){
try{
let params = {
name: this.name,
kana: this.kana,
rank: this.rank,
date: this.date
}
// produces valid object in all cases
await this.$axios.$post('/api/certificate', null, {params})
}catch(err){
console.log(err)
alert(err)
}
}
},
computed:{ // functions from route params, resolve to these always for test case
name: function(){return 'Test Student'},
kana: function(){return "Tesuto Sutuudento"},
rank: function(){return "8th Kyu"},
date: function(){return '26th October, 2020"}
}
}
</script>
/api/certificate.js
var urlencodedParser = bodyParser.urlencoded({ extended: false })
app.post('/', urlencodedParser, function(req, res) {
let response = {
name: req.query.name,
kana: req.query.kana,
rank: req.query.rank,
date: req.query.date
}
console.log(response)
html = html.replace("{{name}}", response.name)
html = html.replace("{{kana}}", response.kana)
html = html.replace("{{rank}}", response.rank)
html = html.replace("{{date}}", response.date) // always produces valid string (template)
pdf.create(html, options).toFile('static/certificates/' + response.name.split(' ')[0] + '_' + response.rank.split(' ')[0] + '_' + response.rank.split(' ')[1] + '.pdf', function(err, rep){
// file made with no difficulties
if (err) return console.log(err);
console.log(rep.filename) // gives absolute path (C:\\)
//res.download('https://get.pxhere.com/photo/computer-screen-technology-web-internet-signage-page-coding-website-html-programming-font-design-text-digital-information-java-site-games-software-development-code-screenshot-data-script-www-css-computer-programming-web-developer-web-development-programming-code-web-page-website-development-670370.jpg') // test fixed path downloading
//res.download(rep.filename,'my_pdf.pdf') // what I think the easiest solution should be
res.download('static/certificates/' + response.name.split(' ')[0]
+ '_' + response.rank.split(' ')[0] + '_'
+ response.rank.split(' ')[1] + '.pdf') // what worked before
})
})
一般来说,我对 API 和 Node 比较陌生,所以我缺少一些基本的东西吗?
解决方案
原来Axios不喜欢下载TXT、HTML、JSON文件以外的任何东西,所以我们需要将生成的文件下载为arraybuffer,然后使用js-file-download将其转成我们想要的文件格式。
下面的例子:
在我的服务器中
import Path from 'path'
import pdf from 'html-pdf'
pdf.create(html, options).toFile('./mypdf.pdf', function(err, rep){
if (err) return console.log(err);
let path = Path.resolve(rep.filename) // ensures we always get the generated path
console.log("resoved path:" + path)
res.setHeader('Content-disposition', 'mypdf.pdf');
res.download(path)
})
在我的客户中:
methods:{
async submit(){
const fileDownloader = require('js-file-download');
try{
let params = {
name: this.name,
kana: this.kana,
rank: this.rank,
date: this.date
}
// use responseType to tell axios its a buffer, using $post instead of post is shorthand for post().data
// not setting this header results in corrupted pdfs
let response = await this.$axios.$post('/api/certificate', null, {params: params, responseType:'arraybuffer'})
console.log(response) // gibberish because Adobe
// create and immediately download. Since we don't want to give a choice, immediate download is fine
fileDownloader(response, 'mypdf.pdf')
}catch(err){
console.log(err)
alert(err)
}
}
},
特别感谢客户端标头的此答案、 js-file-downloader 链接的此答案和服务器端响应标头的此答案。没想到这么棘手。
推荐阅读
- c# - 域逻辑与 Linq-to-Entites 和表达式树
- swift - 如何根据 Swift 中的“if”条件显示两个 Collectionview
- php - 现场 PHP SQL 查询预览
- python - 如何手动排序多索引数据框的索引
- julia - 如何将标准输出重定向到文件和控制台?
- c++ - 为什么析构函数被调用两次?
- linux - 获取状态代码作为 Apache“访问”日志文件格式的输出
- python - 为什么我的 CNN 回归器不起作用(Pytorch)
- c - 如何使用 getch 函数创建流程图?
- javascript - 在 javascript 中设置全局私有类属性的值时出错