PDF Blob没有显示内容,Angular 2

19

我遇到了与此问题非常相似的困扰:PDF Blob - Pop up window not showing content,但我使用的是 Angular 2。该问题的回答是将 responseType 设置为 arrayBuffer,但在 Angular 2 中却不起作用,错误提示是 responseType 不存在于 RequestOptionsArgs 类型中。我还尝试通过 BrowserXhr 进行扩展,但仍然不起作用(https://github.com/angular/http/issues/83)。

我的代码如下:

createPDF(customerServiceId: string) {
   console.log("Sending GET on " + this.getPDFUrl + "/" + customerServiceId);

   this._http.get(this.getPDFUrl + '/' + customerServiceId).subscribe(
       (data) => {
            this.handleResponse(data);
         });
}

而且 handleResponse 方法:

handleResponse(data: any) {
     console.log("[Receipt service] GET PDF byte array " + JSON.stringify(data));

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

我也尝试了FileSaver.js的saveAs方法,但是遇到了同样的问题,PDF文件可以打开,但内容无法显示。谢谢

5个回答

67

我在下载和显示PDF内容方面遇到了很多问题,可能浪费了一两天的时间来解决它,因此我将发布一个可行的示例,以成功下载PDF或在新标签页中打开它:

myService.ts

downloadPDF(): any {
        return this._http.get(url, { responseType: ResponseContentType.Blob }).map(
        (res) => {
            return new Blob([res.blob()], { type: 'application/pdf' })
        }
}

myComponent.ts

this.myService.downloadPDF().subscribe(
        (res) => {
            saveAs(res, "myPDF.pdf"); //if you want to save it - you need file-saver for this : https://www.npmjs.com/package/file-saver

        var fileURL = URL.createObjectURL(res);
        window.open(fileURL); / if you want to open it in new tab

        }
    );

注意

值得一提的是,如果您正在扩展Http类以向所有请求添加headers或类似内容,这也可能会对下载PDF文件造成问题,因为您将覆盖RequestOptions,而我们在其中添加了responseType:ResponseContentType.Blob,这将导致您出现请求主体不是Blob或数组缓冲区错误。


1
当我使用window.open(url)打开PDF文件时,它被浏览器的弹出窗口拦截器阻止了。我们能否重命名该文件?有什么解决方案吗? - Amit Jamwal
1
@PeterAlbert 非常感谢!说实话,我没想到还有其他人会遇到同样的问题。 :) - Stefan Svrkota
1
这对我完美地起作用了,我处理的是一张图片,而不是PDF。 - Ernest
1
我有一个关于如何处理将JWT添加到每个请求中的情况的问题。你愿意帮忙吗?这是链接 - CodeMed
1
传奇,我之前遇到了“请求主体既不是 Blob 也不是 ArrayBuffer”的错误,这个解决方案解决了所有问题,谢谢! - Ka Tech
显示剩余9条评论

4

ANGULAR 5

我曾经也遇到过同样的问题,花费了几天时间才解决。

这里分享一下我的解决方案,希望能帮助别人成功渲染pdf。

即使我将responseType设置为'arraybuffer',它仍然无法接受。

因此,你需要将responseType设置为'arraybuffer'和'json'。(参考链接

以下是可行的代码:

downloadPDF(): any {
    return this._http.get(url, {  responseType: 'blob' as 'json' }).subscribe((res) => {
        var file = new Blob([res], { type: 'application/pdf' });            
        var fileURL = URL.createObjectURL(file);
        window.open(fileURL);
    }
}

参考以下链接

https://github.com/angular/angular/issues/18586


0

这对我有用

 var req = this.getPreviewPDFRequest(fd);
        this.postData(environment.previewPDFRFR, req).then(res => {
          res.blob().then(blob => {
            console.clear();
            console.log(req);
            console.log(JSON.stringify(req));
            const fileURL = URL.createObjectURL(blob);
            window.open(fileURL, '', 'height=650,width=840');
          })
        });

0

服务器端(Java / Jetty):返回文件响应的REST服务 由于注释@Produces(“application/pdf”),Jetty将自动将文件响应解析为pdf blob文件,以便发送到Web客户端并进行阅读。

    @GET
    @Path("/download-pdf/{id}")
    @Produces("application/pdf")
    public Response downloadPDF(@ApiParam(value = "Id of the report record")
                            @PathParam("id") Long id) {
        ResponseBuilder response = null;
        try {
            PDFReportService service = new PDFReportService();
            File reportFile = service.getPDFReportFile(id);

            response = Response.ok((Object) reportFile);  
            response.header("Content-Disposition","attachment; filename="+reportFile.getName());  
            return response.build();
        } catch (DomainException e) {
            response = Response.serverError().entity("server.error");
        }
        return response.build();
    }

客户端代码(Angular 2):获取 Blob 并在新的浏览器选项卡中打印

关键是确保您将请求响应读取为 Blob(因为服务器返回了 Blob;在我的情况下)

现在,我尝试了很多次,但最终发现 Angular 2 没有实现任何处理 Blob 响应的函数(对我来说,res['_body']res.blob() 都不起作用)

所以,我找不到其他解决方法,只能使用 JQuery ajax 来执行文件 Blob 请求,如下所示:

public downloadPDFFile() {
    let fileURL = serverURL+"/download-pdf/"+id;
    let userToken: string = your_token;

    showWaitingLoader();

    $.ajax({
        url: fileURL,
        cache: false,
        headers: {
            "Content-Type": "application/json",
            "Authorization": "Basic " + userToken
        },
        xhrFields: {
            responseType: 'blob' //Most important : configure the response type as a blob
        },
        success: function(blobFile) {
            const url = window.URL.createObjectURL(blobFile);
            window.open(url);
            stopWaitingLoader();
        },
        error: function(e){
            console.log("DOWNLOAD ERROR :", e);
        }
    });
}

0
Amit,你可以通过在字符串末尾添加变量来重命名文件名,例如:saveAs(res, "myPDF.pdf"); 可以变成:
saveAs(res, "myPDF_"+someVariable+".pdf");

其中 someVariable 可能是计数器,或者是我个人最喜欢的日期时间字符串。


抱歉关于答案,我以为我是在给阿米特的问题添加评论。 - Ken
你能帮忙解决这个问题吗?链接为:https://stackoverflow.com/questions/63187758/issue-while-printing-pdf-files-from-blob-agnular - Sunil Garg

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