Я пытаюсь просмотреть PDF-файл, который я получаю из службы с axios.
У меня есть диалоговое окно с кнопкой «Печать», которое открывает другое диалоговое окно, в котором должен быть файл pdf. К сожалению, опора (файл), которую я передаю во втором диалоге, не определена.
Сервисный метод, который я вызываю, просто возвращает byte [], поэтому мой ответ - ArrayBuffer.
Вот код.
ГЛАВНЫЙ ДИАЛОГ
state = {
open: false,
pdf: undefined // my file
}
....
// this prints some data I send to the service and receives a file that I place in my state
print = async table => {
const pdf = await this.props.print(somedata); // send some data to service and get the pdf blob in the response
let fileUrl = URL.createObjectURL(pdf); // create a url
this.setState({ // open the dialog and set the content
pdf: fileUrl,
isPDFDialogOpen: true
});
}
....
render() {
const { isPDFDialogOpen, pdf} = this.state;
return() {
<div>
<DialogContent>
<IconButton><PrintIcon onClick={ () => this.print() } /></IconButton>
</DialogContent>
<SecondDialog open={isPDFDialogOpen} close={this.closePDFViewer} file={pdf}/>
</div>
)
}
ВТОРОЙ ДИАЛОГ
import { Document, Page } from "react-pdf/dist/entry.webpack";
....
render () {
const { file, open, close, title } = this.props;
const { numPages, pageNumber } = this.state;
console.log(file) // returns undefined -> this should be this.props.file
return (
<Dialog
open={ open }
fullScreen
>
<DialogContent>
<Document
file={ file }
onLoadSuccess={ this.onDocumentLoadSuccess }
>
<Page pageNumber={ pageNumber } />
</Document>
<p>Page { pageNumber } of { numPages }</p>
</DialogContent>
<DialogActions>
<Button onClick={ close }>CLOSE</Button>
</DialogActions>
</Dialog>
);
}
AXIOS
export const print = data => {
return axios({
url: `someurl`,
responseType: 'blob',
data: data,
timeout: 20000,
method: 'POST'
}).then(response => {
console.log(response)
return response.data;
}).catch(error => {
if (error.response) {
// DEBUGGING
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
}
});
}
И mapDispatchToProps
const mapDispatchToProps = dispatch => ({
print: (data, type) => print(data, type)
});
Это то, что я получаю - первый журнал console.log(response)
, а второй console.log(response.data)
. Если я сделаю window.open(pdf)
, он откроет новую вкладку и мгновенно закроет ее. Второй диалог просто дает мне Loading PDF…
Я использую "react": "^16.3.1", "react-pdf": "^4.0.5", "@material-ui/core": "^3.4.0", "axios": "^0.18.0",
Я рад любым советам, включая использование других библиотек для просмотра PDF!
EDIT : Я удалил responseType из axios, и теперь я получаю данные, которые выглядят как
. Как мне справиться с этим?
Другие вещи, которые я пробовал:
print = async table => {
const pdf = await this.props.print(somedata, table);
const file = new Blob([pdf], {type: 'application/pdf'});
let fileUrl = URL.createObjectURL(file);
this.setState({ // open the dialog and set the content
pdf: fileUrl,
isPDFDialogOpen: true
});
}
И если я напечатаю fileUrl
, это даст мне blob:http://192.168.1.250:3000/ff3efca5-becd-49df-be83-66c7ff945f80
, и если я попытаюсь открыть его через window.open()
, он откроет вкладку и закроет ее за доли секунды.
РЕДАКТИРОВАТЬ : Я отказался от этого подхода. Для меня работало использование тега <object />
. Теперь я получаю файл, закодированный с base64 как String
, который я декодирую, используя этот метод из Джереми .
Теперь мой код выглядит так:
<div>
<object style={{height: '85vh'}} data={ this.props.file } type="application/pdf" width='100%' height='100%'>alt : <a href="test.pdf"/>
</object>
</div>
Если кто-то знает, почему response-pdf не рендерил мой файл, пожалуйста, добавьте ответ или комментарий!