使用JS消耗Rails send_data响应

时间:2019-02-22 08:35:40

标签: javascript ruby-on-rails vue.js blob wkhtmltopdf

我有一个连接到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的响应,该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

这是上面链接中的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}
}

任何人都可以向我指出正确的方向,例如如何以正确的方式进行配置或如何以其他/更好的方式进行配置?甚至确认响应是哪种数据类型也可能对我有帮助。

1 个答案:

答案 0 :(得分:1)

如果您使用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
    });