将PDF作为字节流下载

6

我有一个Web API,可以将文件保存为字节流。响应已经被获取并保存在状态中,但是现在我想在单击按钮时从我的React应用程序中下载文件。我按如下方式操作:

downloadContract( binaryData ) {
        const file = new Blob([binaryData], { type: 'application/pdf' });
        const fileURL = URL.createObjectURL(file);
        window.open(fileURL);
      }

调试后,流正确获取,但下载文件时出现错误:加载PDF文件时出错。

更新:

使用此来源进行新的端点调用:

  callLoadContract: {
    remote( state, id, contractId ) {
      const url = `${base}/vendor/${id}/${contractId }`;
      return $http.instance.api.get( url, id, contractId);
    },
    success: Actions.contractLoaded,
    error: Actions.fail
  }

处理响应:

  loadContract({id, contractId}) {
    this.getInstance().callLoadContract( id, contractId );
  }

  contractLoaded( response ) {
    if (response && response.data) {
      console.log(response);
      const file = new Blob([response.data], { type: 'application/pdf' });
      const fileURL = URL.createObjectURL(file);
      window.open(fileURL);
    }
  }

同样的错误。


你的JS代码接收哪种响应类型,arraybuffer还是blob? - Carlos Delgado
1
为什么不直接从后端提供服务/api/download?fileId=XXXX - drinchev
我正在获取的JSON对象有多个文档。它们以blob形式存在,我会在一个GET请求中全部获取,然后用户应该选择要查看哪个文档。@CarlosDelgado - user1912404
@drinchev 多个文件属于同一实体。 - user1912404
@drinchev,您能否请检查一下更新? - user1912404
显示剩余2条评论
2个回答

7
也许你的问题与在客户端处理PDF的方式无关,因为你的代码运行得非常好:
import React from 'react';

export default class App extends React.Component {
    constructor(props, context) {
        super(props, context);
    }

    downloadContract() {
        var oReq = new XMLHttpRequest();

        var URLToPDF = "https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf";

        oReq.open("GET", URLToPDF, true);

        oReq.responseType = "blob";

        oReq.onload = function() {
            // Once the file is downloaded, open a new window with the PDF
            // Remember to allow the POP-UPS in your browser
            const file = new Blob([oReq.response], { type: 'application/pdf' });

            const fileURL = URL.createObjectURL(file);

            window.open(fileURL, "_blank");
        };

        oReq.send();
    }

    render() {
        return (
            <div>
                <input type="button" onClick={this.downloadContract} value="Download PDF File"/>
            </div>
        );
    }
}

当用户点击下载时,PDF文件会像预期的那样被下载并显示在浏览器的新窗口中。

然而,最简单的方法是@drinchev所提到的,只需将其放在URL中即可。


我同意你的看法,我们应该调用一个单独的端点来获取文档。只有一个问题,我能否在 Flux 架构中实现相同的想法? - user1912404
它能工作,但没有经过 altjs 处理。我可以接受这样。 - user1912404
对我来说可以工作,但我不想路由到新页面,只想下载。 - Ping Woo

0
这是我的下载文件但不跳转到新页面的解决方案:
try {
            let httpClient = new XMLHttpRequest();
            let pdfLink = "http://localhost/";
            httpClient.open('get', pdfLink, true);
            httpClient.responseType = "blob";
            httpClient.onload = function() {
                const file = new Blob([httpClient.response], { type: 'application/pdf' });
                const fileURL = URL.createObjectURL(file);
                const link = document.createElement("a");
                link.href = fileURL;
                link.download = "fileName.pdf";
                link.click();
                // document.body.removeChild(link);
                URL.revokeObjectURL(fileURL);
            };
            httpClient.send();
        } catch (e) {
            console.log(e);
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接