PDF在使用JavaScript和React JS从API下载时是空白和损坏的。

huangapple go评论109阅读模式
英文:

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生成的文件大小也不为空。我无法找出哪里出错了。

PDF在使用JavaScript和React JS从API下载时是空白和损坏的。

以下是用于fetchFile的API端点的响应:

PDF在使用JavaScript和React JS从API下载时是空白和损坏的。

PDF在使用JavaScript和React JS从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 = &quot;/fetchFile&quot;)	
	public ResponseEntity&lt;byte[]&gt; fetchFile(@RequestParam final String key) {
		FileResponse response = myService.readFile(key);
		HttpHeaders httpHeaders = new HttpHeaders();
		httpHeaders.add(HttpHeaders.CONTENT_DISPOSITION,
				&quot;attachment; filename=\&quot;&quot; + key.substring(key.lastIndexOf(&#39;/&#39;) + 1) + &quot;\&quot;&quot;);
		return Mono.just(ResponseEntity.ok().headers(httpHeaders).contentLength(response.getContentLength())
				.contentType(MediaType.parseMediaType(response.getContentType()))
				.body(response.getResponseBytes()));
	}

Frontend:

rounterFetchFile.js

router.get(&#39;/&#39;, (request, resp) =&gt; {
  axios({
    method: &#39;get&#39;,
    baseURL: &#39;http://mybackend.apibase.url&#39;,
    responseType: &#39;blob&#39;,
    url: &#39;/fetchFile&#39;,
    params: {
      fileKey: &#39;myfile.pdf&#39;
    }    
  })
    .then(response =&gt; {      
      return resp.send(response.data)
    })
    .catch(error =&gt; {
      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 () =&gt; {
      
        try {
            var {data} = await pullMyPDF()
            var blob = new Blob([data], { type: &quot;application/pdf&quot; });
            var link = document.createElement(&#39;a&#39;);
            link.href = window.URL.createObjectURL(blob);
            link.download = &quot;myFileName.pdf&quot;;
            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
PDF在使用JavaScript和React JS从API下载时是空白和损坏的。

Below is the response from API endpoint for the fetchFile
PDF在使用JavaScript和React JS从API下载时是空白和损坏的。

PDF在使用JavaScript和React JS从API下载时是空白和损坏的。

答案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',通过这个配置,任务就完成了 PDF在使用JavaScript和React JS从API下载时是空白和损坏的。 ...

英文:

I had a similar problem and I fixed it with this:

  • spa

             axios.post(
              &#39;api-url&#39;,
              formData,
              {
                responseType: &#39;blob&#39;,
                headers: {
                    &#39;Accept&#39;: &#39;application/pdf&#39;
              }
             })
             .then( response =&gt; {
                  const url = URL.createObjectURL(response.data);
                  this.setState({
                      filePath: url,
                      fileType: &#39;pdf&#39;,
                  })
              })
             .catch(function (error) {
                  console.log(error);
             });
    
  • api

     [HttpPost]
     public async Task&lt;IActionResult&gt; Post()
     {
         var request = HttpContext.Request;
    
         var pdfByteArray = await convertToPdfService.ConvertWordStreamToPdfByteArray(request.Form.Files[0], &quot;application/msword&quot;);
    
         return File(pdfByteArray, &quot;application/pdf&quot;);
     }
    

When the response type is a blob and accepted 'application / pdf' in the header, with that config the job is done PDF在使用JavaScript和React JS从API下载时是空白和损坏的。 ...

答案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&lt;ActionResult&gt; GetAsync() {
    var documentBytes = await GetDocumentAsync().ConfigureAwait(false);
    return Ok(Convert.ToBase64String(documentBytes))
}

Front End:

client.get(url, {
    headers: {
        &#39;Accept&#39;: &#39;application/json&#39;,
        &#39;Content-Type&#39;: &#39;application/json&#39;
    }
})
    .then(response =&gt; {
        const link = document.createElement(&#39;a&#39;);
        link.href = &quot;data:application/octet-stream;base64,&quot; + response.data;
        link.download = &#39;file.pdf&#39;;
        link.click();
    })
    .catch(error =&gt; {
        console.log(error);
    })

I hope this solves your problem.

huangapple
  • 本文由 发表于 2020年9月29日 00:34:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/64106168.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定