jquery - 如何从 ajax 加载的数据中下载 pdf 文件或获取通过 axios 调用我们 Api 的调用快速路由?
问题描述
我尝试下载我们的 API 生成的 pdf 文件。
流程:单击“下载”按钮触发获取快速路线的功能。路由通过 axios 调用我们的 API。API 生成一个 pdf 并返回一个原始数据 pdf 文件(字符串)。路由得到axios的响应。为了将此响应发送回 fetch,我将响应放入对象 {pdf: response} 并使用 res.json({pdf: response}) 将其发送回。在 fetch.then() 中,我需要将响应转换为 blob 并在其上使用 URL.createObjectURL 创建一个不可见的下载链接以触发点击它并开始下载。
问题: res.json({pdf: response}) 发送的响应无法转换为blob,因为它不是pdf数据,它是一个包含pdf数据的json。
按钮点击触发的动作:
var url = "/routePath";
fetch(url)
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
// the filename you want
a.download = couponName + '.pdf';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
.catch((error) => console.error(error));
服务器端的快速路由处理:
router.get('/routePath', async function(req, res, next) {
const pdf = await Api.send(req, 'entity', 'action', {data}, {});
res.json({pdf: pdf});
});
通过 Axios 调用:
const config = require(`../config/config.${process.env.NODE_ENV}.json`);
const axios = require('axios');
module.exports = {
send: async function(req, entity, action, data, pathValues){
let response = false;
try {
// Prepare headers
let headers = {'Content-Type': 'application/json'};
// Request
let axiosConfig = {
method: 'get',
headers,
url: path,
data: data,
validateStatus: false
};
axiosConfig.params = data;
response = await axios(axiosConfig);
if (response.data == '') response.data = {};
response = response.data;
response.callSuccess = true;
} catch(error) {
console.error(error);
if (error.response){
response = error.response.data;
response.callSuccess = false;
console.error(response);
}
else {
console.error(error);
}
}
return response;
}
}
解决方案
客户端:
我为 Ajax 切换了 Fetch 以获得更多的兼容性(即)。我还使用 base64ToArrayBuffer 进行转换,接收到的 pdf 数据能够将其转换为 blob。
[...]
var url = "/routePath";
$.ajax({ url: url })
.done(function(pdf) {
const arraybuffer = base64ToArrayBuffer(pdf);
const blob = new Blob([arraybuffer], {type: 'application/pdf'});
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'GoCoupons.' + couponName + '.pdf';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
.fail(function(error) {
console.error(error);
})
[...]
function base64ToArrayBuffer(data) {
var binaryString = window.atob(data);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
}
服务器端:
我没有返回 json,而是从我们的 API 发送 pdf 响应。
router.get('/routePath', async function(req, res, next) {
const pdf = await Api.send(req, 'entity', 'action', {data}, {});
res.send(pdf);
});
axios调用还是一样
const config = require(`../config/config.${process.env.NODE_ENV}.json`);
const axios = require('axios');
module.exports = {
send: async function(req, entity, action, data, pathValues){
let response = false;
try {
// Prepare headers
let headers = {'Content-Type': 'application/json'};
// Request
let axiosConfig = {
method: 'get',
headers,
url: path,
data: data,
validateStatus: false
};
axiosConfig.params = data;
response = await axios(axiosConfig);
if (response.data == '') response.data = {};
response = response.data;
response.callSuccess = true;
} catch(error) {
console.error(error);
if (error.response){
response = error.response.data;
response.callSuccess = false;
console.error(response);
}
else {
console.error(error);
}
}
return response;
}
}
推荐阅读
- lua - 试图将“self”索引为 nil 值
- cmake - Zephyr / PlatformIO / CMake / 外部代码
- linux - 输入中两个命令的 Linux ssh 输出
- python - Default MaxPoolingOp only support NHWC on device type CPU [[{{node maxpool4/MaxPool}}]] 是什么意思?
- javascript - javascript中奇怪的日期问题
- azure-cosmosdb - 从 Document DB SDK (2.7.0) 更新到 Cosmos SDK (3.12.0)
- php - 如何确定生成器是否通过引用产生?
- firebase - 访问我的 Firebase 托管网络应用程序(无自定义 URL)后,如何解决“ERR CERT COMMON NAME INVALID”页面?
- sql-server - 拆分句子并在sql中仅选择所需的字符串
- reactjs - TypeScript 重新分配 InputHTMLAttributes