如何实现带有打印功能的react-pdf
How to implement react-pdf with print function
我想用react-pdf来显示PDF并开发一个打印功能直接打印(比如用window.print());
REST 服务器是使用 Jersey 开发的。
PDF 将从服务器生成,return 到使用 return 类型为 application/pdf 的 Jersey 的 React 客户端。 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;
axios.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 内容)
代码如下:
componentDidMount(){
var that = this;
axios.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);
});
}
谁能给我一些建议?
或者有什么更好的方式来实现我的目标?
谢谢
最近收到一个类似pdf部分的用例,我的要求是Post,不过你可以毫无问题的搞定。那么,发生了什么:
1) - 我正在使用 axios 向后端发出请求:
2) - request 是我发送的对象,但你不会有这样的对象,因为你可能只会发送 id,例如:axios.get ('here.is.your/endpoint/id');
3) - 我正在使用:文件保护程序来保存我收到的文件。
其余代码应该是自解释的,我还添加了一些注释。
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"
});
});
我仍然无法从后端收到错误消息,如果我在这方面取得了一些进展,我会发回短信 - 现在,我会显示一条自定义消息。
希望对您有所帮助!
祝你好运!
收到来自 back-end 的错误消息更新:
当请求失败时,我们会收到来自 back-end 的 JSON object,其中包含错误消息。问题是当我们强制接收 Blob 格式的响应时:responseType: 'blob' - 无论请求是否失败,我们都会收到一个 Blob Object。所以,我正在考虑更改 axios 提供的函数中的 responseType:transformResponse,但不幸的是,我们无法访问 'responseType' object,只能访问 headers。此处: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
});
});
希望对您有所帮助!
很高兴能帮上忙!
我还有一个收到错误消息的更新
仅当您收到的短信不是 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 转换为文本。使用 .then() 很重要,因为此时 Promise 已解决并且我们收到了 Promise 值。然后我们简单地抛出一个错误,因为我们无权访问状态对象。
这就是您从回复中获取文本的方式。
我想用react-pdf来显示PDF并开发一个打印功能直接打印(比如用window.print());
REST 服务器是使用 Jersey 开发的。
PDF 将从服务器生成,return 到使用 return 类型为 application/pdf 的 Jersey 的 React 客户端。 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;
axios.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 内容)
代码如下:
componentDidMount(){
var that = this;
axios.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);
});
}
谁能给我一些建议? 或者有什么更好的方式来实现我的目标?
谢谢
最近收到一个类似pdf部分的用例,我的要求是Post,不过你可以毫无问题的搞定。那么,发生了什么:
1) - 我正在使用 axios 向后端发出请求:
2) - request 是我发送的对象,但你不会有这样的对象,因为你可能只会发送 id,例如:axios.get ('here.is.your/endpoint/id');
3) - 我正在使用:文件保护程序来保存我收到的文件。
其余代码应该是自解释的,我还添加了一些注释。
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"
});
});
我仍然无法从后端收到错误消息,如果我在这方面取得了一些进展,我会发回短信 - 现在,我会显示一条自定义消息。
希望对您有所帮助!
祝你好运!
收到来自 back-end 的错误消息更新:
当请求失败时,我们会收到来自 back-end 的 JSON object,其中包含错误消息。问题是当我们强制接收 Blob 格式的响应时:responseType: 'blob' - 无论请求是否失败,我们都会收到一个 Blob Object。所以,我正在考虑更改 axios 提供的函数中的 responseType:transformResponse,但不幸的是,我们无法访问 'responseType' object,只能访问 headers。此处: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
});
});
希望对您有所帮助!
很高兴能帮上忙!
我还有一个收到错误消息的更新
仅当您收到的短信不是 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 转换为文本。使用 .then() 很重要,因为此时 Promise 已解决并且我们收到了 Promise 值。然后我们简单地抛出一个错误,因为我们无权访问状态对象。
这就是您从回复中获取文本的方式。