使用 JS 消费 Rails send_data 响应
Using JS to consume a Rails send_data response
我有一个连接到 Rails API 后端的 VueJS 前端。
在其中一个端点中,我正在使用 WickedPDF 生成 PDF。当我在浏览器中打开 URL 本身时,PDF 下载正常并且完全按预期工作。当我通过 Vue 发送请求时,API 响应一个看起来很奇怪的字符串,如下所示:
%PDF-1.4
1 0 obj
<<
/Title (��)
/Creator (��wkhtmltopdf 0.12.4)
/Producer (��Qt 4.8.7)
/CreationDate (D:20190222102025+02'00')
>>
endobj
3 0 obj
<<
/Type /ExtGState
/SA true
/SM 0.02
/ca 1.0
/CA 1.0
/AIS false
...
我不确定这是什么数据类型?我最初认为它可能是一个 BLOB,但我不知道。我按照概述的逻辑 here 来解析来自我的 rails api 的响应,它确实将 PDF 下载到 chrome。打开此 PDF 时,它是空白的,chrome 浏览器顶部的文件名是一组奇怪的字符。这让我觉得我没有以正确的方式转换响应,最终发生了一些编码问题。
这是我的 Rails API 代码:
def pdf
pdf_html = ActionController::Base.new.render_to_string(
template: 'api/v1/exporters/pdf',
layout: 'pdf',
page_size: 'A4',
formats: :html,
encoding: 'utf8',
margin: {
top: 20,
left: 20,
}
)
pdf = WickedPdf.new.pdf_from_string(pdf_html)
send_data(
pdf,
filename: 'download.pdf',
type: 'application/pdf',
disposition: 'attachment'
)
end
这里是上面link的JS函数。我正在传递 Rails 响应主体(当控制台登录时,它是第一个代码块中设置的奇怪的字符集)作为唯一的参数:
showFile(blob){
var newBlob = new Blob([blob], {type: "application/pdf"})
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob);
return;
}
const data = window.URL.createObjectURL(newBlob);
var link = document.createElement('a');
link.href = data;
link.download="file.pdf";
link.click();
setTimeout(function(){
window.URL.revokeObjectURL(data);
, 100}
}
任何人都可以帮助我指明正确的方向,以了解如何以正确的方式配置它或如何以 different/better 的方式进行配置吗?即使确认响应是哪种数据类型也可能对我有所帮助。
如果您使用 axios 进行 API 调用,您可以指定客户端以 blob 形式下载数据。
import axios from 'axios';
axios
.request({
url: '/api-url-to-download-pdf',
responseType: 'blob',
})
.then(response => response.data)
.then(blob => {
const data = URL.createObjectURL(blob );
// ... do your stuff here ...
.catch((err) => {
// handle error
});
如果您使用 fetch api 发出 API 请求,
fetch('/api-url-to-download-pdf', {
headers: {
Accept: 'application/pdf',
},
responseType: 'arraybuffer'
})
.then(response => {
console.log(response);
if (response.ok) {
return response.blob();
}
})
.then(blob => {
const data = URL.createObjectURL(blob);
// ... do your stuff here ...
})
.catch((err) => {
// handle error
});
我有一个连接到 Rails API 后端的 VueJS 前端。
在其中一个端点中,我正在使用 WickedPDF 生成 PDF。当我在浏览器中打开 URL 本身时,PDF 下载正常并且完全按预期工作。当我通过 Vue 发送请求时,API 响应一个看起来很奇怪的字符串,如下所示:
%PDF-1.4
1 0 obj
<<
/Title (��)
/Creator (��wkhtmltopdf 0.12.4)
/Producer (��Qt 4.8.7)
/CreationDate (D:20190222102025+02'00')
>>
endobj
3 0 obj
<<
/Type /ExtGState
/SA true
/SM 0.02
/ca 1.0
/CA 1.0
/AIS false
...
我不确定这是什么数据类型?我最初认为它可能是一个 BLOB,但我不知道。我按照概述的逻辑 here 来解析来自我的 rails api 的响应,它确实将 PDF 下载到 chrome。打开此 PDF 时,它是空白的,chrome 浏览器顶部的文件名是一组奇怪的字符。这让我觉得我没有以正确的方式转换响应,最终发生了一些编码问题。
这是我的 Rails API 代码:
def pdf
pdf_html = ActionController::Base.new.render_to_string(
template: 'api/v1/exporters/pdf',
layout: 'pdf',
page_size: 'A4',
formats: :html,
encoding: 'utf8',
margin: {
top: 20,
left: 20,
}
)
pdf = WickedPdf.new.pdf_from_string(pdf_html)
send_data(
pdf,
filename: 'download.pdf',
type: 'application/pdf',
disposition: 'attachment'
)
end
这里是上面link的JS函数。我正在传递 Rails 响应主体(当控制台登录时,它是第一个代码块中设置的奇怪的字符集)作为唯一的参数:
showFile(blob){
var newBlob = new Blob([blob], {type: "application/pdf"})
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(newBlob);
return;
}
const data = window.URL.createObjectURL(newBlob);
var link = document.createElement('a');
link.href = data;
link.download="file.pdf";
link.click();
setTimeout(function(){
window.URL.revokeObjectURL(data);
, 100}
}
任何人都可以帮助我指明正确的方向,以了解如何以正确的方式配置它或如何以 different/better 的方式进行配置吗?即使确认响应是哪种数据类型也可能对我有所帮助。
如果您使用 axios 进行 API 调用,您可以指定客户端以 blob 形式下载数据。
import axios from 'axios';
axios
.request({
url: '/api-url-to-download-pdf',
responseType: 'blob',
})
.then(response => response.data)
.then(blob => {
const data = URL.createObjectURL(blob );
// ... do your stuff here ...
.catch((err) => {
// handle error
});
如果您使用 fetch api 发出 API 请求,
fetch('/api-url-to-download-pdf', {
headers: {
Accept: 'application/pdf',
},
responseType: 'arraybuffer'
})
.then(response => {
console.log(response);
if (response.ok) {
return response.blob();
}
})
.then(blob => {
const data = URL.createObjectURL(blob);
// ... do your stuff here ...
})
.catch((err) => {
// handle error
});