如何使用print函数实现react-pdf

问题描述 投票:0回答:3

我想使用react-pdf来显示PDF并开发直接打印的打印功能(比如使用window.print());

REST服务器是使用Jersey开发的。

PDF将从服务器生成并使用Jersey返回到React客户端,返回类型为application / pdf。 React客户端将使用react-pdf显示PDF。

我不想在“文件”中声明URL路径,因为如果React状态发生更改并触发重新呈现,这将再次从服务器检索PDF。另外,我需要开发一个打印功能来打印显示的PDF(因为如果从服务器再次检索PDF,PDF内容可能会改变)

下面显示我的代码:

服务器:

@Override
@GET
@Path("/pdf")
@Produces(MediaType.APPLICATION_PDF_VALUE)
public Response testPdf() throws Exception {

    File file = new File("C:\\Desktop\\test.pdf");
    FileInputStream fileInputStream = new FileInputStream(file);

    ResponseBuilder response = Response.ok((Object) fileInputStream);
    response.type("application/pdf");
    response.header("Content-Disposition", "filename=test.pdf");

    return response.build();
}

客户

import React, { Component } from 'react';
import { Document, Page } from 'react-pdf';
import axios from 'axios';

class MyApp extends Component {
    state = {
        numPages: null,
        pageNumber: 1,
        pdfContent: null
    }

    componentDidMount(){
        var that = this;

        axio.get("url\Pdf).then((response) => {
             that.setState({pdfContent:response.data});
        }).catch((error) => {
             console.warn(error);
        });
    }

    onDocumentLoadSuccess = ({ numPages }) => {
        this.setState({ numPages });
    }

   printHandler(){
       window.print();
   }

   render() {
      const { pageNumber, numPages } = this.state;

      return (
          <div>
             <Document
                file={this.state.pdfContent}
                onLoadSuccess={this.onDocumentLoadSuccess}
             >
                 <Page pageNumber={pageNumber} />
             </Document>
             <p>Page {pageNumber} of {numPages}</p>

             <button onClick={() => this.setState(prevState => ({ 
                     pageNumber: prevState.pageNumber + 1 }))}>Next page</button>
             <button onClick={() => this.setState(prevState => ({ 
                     pageNumber: prevState.pageNumber - 1 }))}>Prev Page</button>

              <button onClick={this.printHandler}/>
          </div>
      );

} }

我想只获取一次PDF并使用react-pdf显示PDF。另外,我想打印显示的PDF。

我试图将response.data转换为base64,因为没有成功:(这将失去pdf内容)Encode PDF to base64 in ReactJS

代码如:

  componentDidMount(){
        var that = this;

        axio.get("url\Pdf).then((response) => {
             let reader = new FileReader();
            var file = new Blob([response.data], { type: 'application/pdf' });

            reader.onloadend = () => {
                that.setState({
                    base64Pdf:reader.result
                });
            }
            reader.readAsDataURL(file);
        }).catch((error) => {
             console.warn(error);
        });
    }

有人可以给我一些建议吗?或者更好的方式达到我的目标?

谢谢

reactjs pdf jersey state react-pdf
3个回答
1
投票

从后端接收错误消息的更新:

当请求失败时,我们从后端收到一个包含错误消息的JSON对象。问题是当我们强制以Blob格式接收响应时:responseType:'blob' - 无论请求是否失败,我们都会收到一个Blob对象。所以,我正在考虑更改axios:transformResponse提供的函数中的responseType,但不幸的是,我们无法访问'responseType'对象,只能访问标题。这里:https://github.com/axios/axios/pull/1155有一个关于转换为responseType的公开问题,它仍然没有得到解决。

所以,我解决这个问题的方法是使用fetch而不是axios。这是一个例子:

fetch('here.is.your/endpoint', {
            method: 'POST', // specifying the method request
            body: JSON.stringify(request), // specifying the body
            headers: {
                "Content-Type": "application/json"
            }
        }
    ).then((response) => {
        if (response.ok) { // checks if the response is with status 200 (successful)
            return response.blob().then(blob => {
                const name = 'Report.pdf';
                saveAs(blob, name);
            });
        } else {
            return response.json().then((jsonError) => {
                this.setState({
                    modalMessage: jsonError.message // access the error message returned from the back-end
                });
            });
        }
    }).catch(function (error) {
        this.setState({
            modalMessage: "Error in data type received." // general handler
        });
    });

我希望这有帮助!


1
投票

最近我得到了一个与pdf部分类似的用例,我的请求是Post,但你可以让它得到没问题。那么,发生了什么:

1) - 我正在使用axios向后端发出请求:

2) - 请求是我发送的对象,但你不会有这样的,因为你可能只发送id,例如:axios.get('here.is.your / endpoint / id');

3) - 我正在使用:file-saver来保存我收到的文件。

其余的代码应该是自我解释的,我还添加了一些注释。

import {saveAs} from "file-saver";
...

axios.post('here.is.your/endpoint', qs.parse(request), {
       headers: {
          'Content-Type': 'application/json'
       },   
       responseType: 'blob' // here I am forcing to receive data in a Blob Format
    })
    .then(response => {
        if (response.data) {
            //Create a Blob from the PDF Stream
            const file = new Blob(
                [response.data],
                {type: 'application/pdf'});
            const name = 'Report.pdf';
            saveAs(file, name);
        } else {
            throw new Error("Error in data type received.");
        }
    })
    .catch(error => {
        this.setState({
            modalMessage: "Here Add Custom Message"
        });
   });

我仍然无法从后端收到错误消息,如果我在其上取得一些进展,我会发回文本 - 现在,我会显示一条自定义消息。

我希望有所帮助!

祝你好运!


0
投票

我很高兴我帮了!

我还有一个更新收到错误消息的更新

如果您收到的文字信息不是JSON,那么这一项是有效的

fetch('here.is.your/endpoint', {
        method: 'POST', // specifying the method request
        body: JSON.stringify(request), // specifying the body
        headers: {
            "Content-Type": "application/json"
        }
    }
).then((response) => {
    if (response.ok) { // checks if the response is with status 200 (successful)
        return response.blob().then(blob => {
            const name = 'Report.pdf';
            saveAs(blob, name);
        });
    } else {
         return response.text().then(function (error) {
                    throw new Error(error); // we should throw an Error with the received error
                }
            );
    }
}).catch(function (error) {
    this.setState({
        modalMessage: error.message // that way we access the error message
    });
});

我们正在使用response.text()。then(),因为我们设法将它从Promise转换为text。使用.then()非常重要,因为当时的Promise已经解决,我们收到了Promise值。然后我们简单地抛出一个错误,因为我们无法访问状态对象。

这就是您从响应中获取文本的方式。

© www.soinside.com 2019 - 2024. All rights reserved.