英文:
PDF is blank and damaged when downloading it from API using JavaScript and React JS
问题
我正在从API下载一个PDF文件,但是我得到了一个空白的PDF。我已经测试了API端点,能够在控制台上获取字节流,并且当我将其保存到文件时,它被成功保存,文件看起来正常。但是当我将相同的响应传递给React前端时,我可以看到响应中的PDF字节流,但无法看到内容。当我从本地打开下载的PDF时,它显示文件已损坏或损坏。我查看了许多示例并按照相同的模式进行操作,但我认为我在这里漏掉了什么。
我的API Java端点定义如下:
@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()));
}
前端:
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()
})
})
在myFileComoponent.js
中:
// 从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)
}
}
这里
var {data} = await pullMyPDF()
返回以下内容。我将其与Postman返回的结果进行了比较,它是相同的。从React生成的文件大小也不为空。我无法找出哪里出错了。
以下是用于fetchFile的API端点的响应:
英文:
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 compared 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
答案1
得分: 3
我遇到过类似的问题,我用以下方法解决了:
- 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");
}
当响应类型为 blob,且在请求头中接受了 'application/pdf',通过这个配置,任务就完成了 ...
英文:
I 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 ...
答案2
得分: 0
以下是翻译好的内容:
在控制器中,对我有效的方法是将字节作为 base64 进行发送。
API:
public async Task<ActionResult> GetAsync() {
var documentBytes = await GetDocumentAsync().ConfigureAwait(false);
return Ok(Convert.ToBase64String(documentBytes));
}
前端:
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);
})
我希望这解决了你的问题。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论