I am downloading a pdf file from API, but I am getting a blank PDF. I have tested the API endpoint and able to get the byte stream on the console and when I save it to File, it got saved and the file looks good. Getting the same response back to the front end using React and I could see the PDF byte stream in the response.
However, I could not see the content. It says the file is damaged or corrupted
when I opened the downloaded PDF from my local.
I have looked at many examples and are following the same pattern, but I think I am missing something here.
My API Java endpoint definition looks like below
@GetMapping(value = "/fetchFile")
public ResponseEntity<byte[]> fetchFile(@RequestParam final String key) {
FileResponse response = myService.readFile(key);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + key.substring(key.lastIndexOf('/') + 1) + "\"");
return Mono.just(ResponseEntity.ok().headers(httpHeaders).contentLength(response.getContentLength())
.contentType(MediaType.parseMediaType(response.getContentType()))
.body(response.getResponseBytes()));
}
Frontend:
rounterFetchFile.js
router.get('/', (request, resp) => {
axios({
method: 'get',
baseURL: '',
responseType: 'blob',
url: '/fetchFile',
params: {
fileKey: 'myfile.pdf'
}
})
.then(response => {
return resp.send(response.data)
})
.catch(error => {
console.error(error)
return resp.status(error.response.status).end()
})
})
in myFileComoponent.js
//a function that reads the response from rounterFetchFile.js
const getDocumentOnClick = async () => {
try {
var {data} = await pullMyPDF()
var blob = new Blob([data], { type: "application/pdf" });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "myFileName.pdf";
link.click();
} catch (e) {
console.log(e)
}
}
Here
var {data} = await pullMyPDF()
is returning the following content. I pared it with the result returned by the Postman, and it is the same. The generated file size is not empty from the react too. I am not able to find out where is it wrong
Below is the response from API endpoint for the fetchFile
I am downloading a pdf file from API, but I am getting a blank PDF. I have tested the API endpoint and able to get the byte stream on the console and when I save it to File, it got saved and the file looks good. Getting the same response back to the front end using React and I could see the PDF byte stream in the response.
However, I could not see the content. It says the file is damaged or corrupted
when I opened the downloaded PDF from my local.
I have looked at many examples and are following the same pattern, but I think I am missing something here.
My API Java endpoint definition looks like below
@GetMapping(value = "/fetchFile")
public ResponseEntity<byte[]> fetchFile(@RequestParam final String key) {
FileResponse response = myService.readFile(key);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + key.substring(key.lastIndexOf('/') + 1) + "\"");
return Mono.just(ResponseEntity.ok().headers(httpHeaders).contentLength(response.getContentLength())
.contentType(MediaType.parseMediaType(response.getContentType()))
.body(response.getResponseBytes()));
}
Frontend:
rounterFetchFile.js
router.get('/', (request, resp) => {
axios({
method: 'get',
baseURL: 'http://mybackend.apibase.url',
responseType: 'blob',
url: '/fetchFile',
params: {
fileKey: 'myfile.pdf'
}
})
.then(response => {
return resp.send(response.data)
})
.catch(error => {
console.error(error)
return resp.status(error.response.status).end()
})
})
in myFileComoponent.js
//a function that reads the response from rounterFetchFile.js
const getDocumentOnClick = async () => {
try {
var {data} = await pullMyPDF()
var blob = new Blob([data], { type: "application/pdf" });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "myFileName.pdf";
link.click();
} catch (e) {
console.log(e)
}
}
Here
var {data} = await pullMyPDF()
is returning the following content. I pared it with the result returned by the Postman, and it is the same. The generated file size is not empty from the react too. I am not able to find out where is it wrong
Below is the response from API endpoint for the fetchFile
Share Improve this question edited Sep 28, 2020 at 19:34 mark asked Sep 28, 2020 at 16:34 markmark 4179 silver badges29 bronze badges 8- Is there a specific reason you convert the byte stream in React instead of fetching the PDF directly from the back-end (send out application/pdf)? – Fullslack Commented Sep 28, 2020 at 16:42
- @Fullslack.dev, as per my knowledge, yes the PDF is sending application/pdf from the backend only in my example. The response type is byte[]. I tried with the Resource as response type from the API endpoint, it is still the same issue – mark Commented Sep 28, 2020 at 17:14
- technicalkeeda./spring-tutorials/… – Fullslack Commented Sep 28, 2020 at 17:26
- @Fullslack.dev, I checked the response headers, I got the same values what you have referenced in the link. Updated post with the response received in postman from API – mark Commented Sep 28, 2020 at 18:00
- Again: why is the return type of your ResponseEntity in Java a byte[] and not a InputStream? Then you also convert the byte[] to a blob and pass it around to finally trying to make a PDF out of it. Multiple conversions is bound to cause a error and a corrupted file in the end. Btw I don't consider React a back-end, for me that ends when you leave the Java code in this example. – Fullslack Commented Sep 28, 2020 at 19:24
2 Answers
Reset to default 5I had a similar problem and I fixed it with this:
spa
axios.post( 'api-url', formData, { responseType: 'blob', headers: { 'Accept': 'application/pdf' } }) .then( response => { const url = URL.createObjectURL(response.data); this.setState({ filePath: url, fileType: 'pdf', }) }) .catch(function (error) { console.log(error); });
api
[HttpPost] public async Task<IActionResult> Post() { var request = HttpContext.Request; var pdfByteArray = await convertToPdfService.ConvertWordStreamToPdfByteArray(request.Form.Files[0], "application/msword"); return File(pdfByteArray, "application/pdf"); }
When the response type is a blob and accepted 'application / pdf' in the header, with that config the job is done ;) ...
Something that worked for me was to send the bytes as base64 from the controller.
API:
public async Task<ActionResult> GetAsync() {
var documentBytes = await GetDocumentAsync().ConfigureAwait(false);
return Ok(Convert.ToBase64String(documentBytes))
}
Front End:
client.get(url, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => {
const link = document.createElement('a');
link.href = "data:application/octet-stream;base64," + response.data;
link.download = 'file.pdf';
link.click();
})
.catch(error => {
console.log(error);
})
I hope this solves your problem.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744940542a4602295.html
评论列表(0条)