【问题标题】:Spring REST - Damaged/Blank File being downloadedSpring REST - 正在下载损坏/空白文件
【发布时间】:2018-10-07 03:20:28
【问题描述】:

我正在尝试创建一个端点来呈现/提供 PDF 文件。 我已通过以下链接构建 API,但仍面临一些问题。

link 1

link 2

以下是我的代码:

byte[] targetArray = null;

InputStream is = null;

InputStream objectData = object.getObjectContent();

BufferedReader reader = new BufferedReader(new InputStreamReader(objectData));

char[] charArray = new char[8 * 1024];
StringBuilder builder = new StringBuilder();
int numCharsRead;
while ((numCharsRead = reader.read(charArray, 0, charArray.length)) != -1) {

    builder.append(charArray, 0, numCharsRead);
}
reader.close();

objectData.close();
object.close();
targetArray = builder.toString().getBytes();

is = new ByteArrayInputStream(targetArray);


return ResponseEntity.ok().contentLength(targetArray.length).contentType(MediaType.APPLICATION_PDF)
                .cacheControl(CacheControl.noCache()).header("Content-Disposition", "attachment; filename=" + "testing.pdf")
                .body(new InputStreamResource(is));

当我使用邮递员访问我的 API 时,我可以下载 PDF 文件,但问题是它完全是空白的。可能是什么问题?

【问题讨论】:

  • 嗯...为什么要将PDF读入char的数组,将其转换为String,然后从字符串中提取字节?你明白字符数据和二进制数据的区别吧?
  • 另外,既然您的数据已经有一个InputStream,为什么不使用您提到的第一个链接中的InputStreamResource
  • 实际上我正在尝试从远程位置获取 PDF 文件的内容,该位置正在流式传输我的 PDF 文件内容。
  • 很公平,但是由于您使用InputStream 对其进行操作,因此对您来说应该是透明的。当您直接返回 InputStreamResource 包装 objectData 时会发生什么?为什么你觉得你需要所有的中间步骤?
  • 其实InputStream是S3ObjectInputStream

标签: java spring spring-boot postman


【解决方案1】:

从服务器下载文件有多种方式,您可以使用ResponseEntity<InputStreamResource>HttpServletResponse。以下是两种下载方式。

@GetMapping("/download1")
       public ResponseEntity<InputStreamResource> downloadFile1() throws IOException {

          File file = new File(FILE_PATH);
          InputStreamResource resource = new InputStreamResource(new FileInputStream(file));

          return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION,
                      "attachment;filename=" + file.getName())
                .contentType(MediaType.APPLICATION_PDF).contentLength(file.length())
                .body(resource);
       }

您可以使用StreamingResponseBody 下载文件。在这种情况下,服务器将数据写入OutputStream,同时浏览器读取数据,这意味着它是并行的。

@RequestMapping(value = "downloadFile", method = RequestMethod.GET)
    public StreamingResponseBody getSteamingFile(HttpServletResponse response) throws IOException {
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=\"demo.pdf\"");
        InputStream inputStream = new FileInputStream(new File("C:\\demo-file.pdf"));
        return outputStream -> {
            int nRead;
            byte[] data = new byte[1024];
            while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
                System.out.println("Writing some bytes..");
                outputStream.write(data, 0, nRead);
            }
        };
    }

【讨论】:

    【解决方案2】:

    你可以尝试使用apache commons IOUtils。为什么要重新发明轮子:) 1.打开与远程服务器的连接 2.将inputStream复制到目标文件outputStream。

    public void downloadFileFromRemoteLocation(String serverlocation, File destinationFile) throws IOException
    {
        try (FileOutputStream fos = new FileOutputStream( destinationFile )){
            URL url = new URL(serverlocation);
            URLConnection connection = url.openConnection();
            IOUtils.copy( connection.getInputStream(),  fos);
        } 
    }
    

    如果您只想坚持 Java,请查看下面的 sn-p

    try {
            // Get the directory and iterate them to get file by file...
            File file = new File(fileName);
    
            if (!file.exists()) {
                context.addMessage(new ErrorMessage("msg.file.notdownloaded"));
                context.setForwardName("failure");
            } else {
                response.setContentType("APPLICATION/DOWNLOAD");
                response.setHeader("Content-Disposition", "attachment"+ 
                                         "filename=" + file.getName());
                stream = new FileInputStream(file);
                response.setContentLength(stream.available());
                OutputStream os = response.getOutputStream();      
                os.close();
                response.flushBuffer();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2017-05-15
      • 2015-01-17
      • 1970-01-01
      • 2018-06-21
      • 2021-02-15
      • 2015-07-14
      • 2015-07-16
      • 2017-12-04
      • 2019-01-28
      相关资源
      最近更新 更多