Remember once that the Zip file generated by the backend is corrupted after being downloaded by the browser, and cannot be opened, unpredictable end errors, and the downloaded file is larger than the original file

foreword

On the eve of the project’s launch, a data export interface was temporarily added. The requirement was to export the compressed package. The download interface normally used in the project was selected for modification, but the file compression function was added to the file generation function.

There was a problem

However, in the interface downloaded normally in other places, the downloaded compressed package cannot be opened, and it prompts 压缩包损坏, 不可预料的压缩文件末端, the generated compressed package is 205kb, after downloading, it is370kb

insert image description here

Troubleshoot

By facing Baidu, I got several answers 流没关好, 写入使用了字节数组导致多写入空字节, 流没有flushetc.

1. The flow is not closed properly

1. Check whether the output stream of the program is closed.
2. Whether the order of closing the stream is correct.
But my stream uses try-with-resourcea method, and there is no need to close the operation stream.

try (
    // 1.读取要下载的内容
    BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file));
        // 将要下载的文件内容通过输出流写到浏览器
        ServletOutputStream outputStream = response.getOutputStream()) {
    
    
        //do something
        } catch (IOException e) {
    
    
      e.printStackTrace();
    }

Extension: If you don’t use try-with-resourcethe method, you can read this article to avoid that the zip created by java cannot be opened due to flow problems
or open and display unpredictable compressed files (https://blog.csdn.net/freedom_zzc/article/details/118930027 )

2. Blank bytes are written

If the writing method is wrong when writing through the stream, a null byte will be written into the file during the last write, causing the file to fail to open. The
wrong writing method:
不能直接用output.write(buffer) . Otherwise more bytes will be written than actual if the final stream does not completely fill the buffer

	  byte[] b = new byte[2048];
      int len;
      while ((len = inputStream.read(b)) > 0) {
    
    
        outputStream.write(b);
      }

Correct spelling:

	  byte[] b = new byte[2048];
      int len;
      while ((len = inputStream.read(b)) > 0) {
    
    
        outputStream.write(b, 0, len);
      }

Three, no flush

If there is no flush stream, the data is still there 文件缓冲区, and the data has not been actually written 物理介质. If the service hangs, the file will be lost.

But if you directly call the internal close method, the internal flush method will be called first
insert image description here

In fact, you can directly use the copy of the tool class to avoid the above problems, and the code is more concise

hutool包中工具类
      IoUtil.copy(inputStream, outputStream);

insert image description here

So my problem has nothing to do with the stream

At this point the issue reached an impasse

Positioning link

Decided to troubleshoot to see which part of the problem is being modified

1. Generation

Manually download the compressed package generated by the program on the server to the local, open it and find that there is no problem, no error will be reported, make sure 生成环节there is no problem, and continue

2. Download through SwaggerUI and PostMan

Downloaded through the tool, found that the file size is normal, can be opened normally, no error is reported, sure 下载接口there is no problem

3. Conclusion

At present, it can be determined that the problem occurs in the foreground call, and the problem of downloading the compressed package is solved by modifying the front-end call interface.

solve

The final solution is to add responseType: ‘blob‘parameters to the foreground call interface
. The code example is as follows:

  1. Front-end blob download, responseType: 'blob' (https://blog.csdn.net/weixin_40994437/article/details/122425671)
  2. The problem of exporting file type as responseType:blob (https://blog.csdn.net/weixin_43123717/article/details/116125289)

method

The method was wrong at the beginning. You should not modify the back-end code directly. Empiricism kills people. I habitually think that there is a problem with writing files (a similar problem occurred when I downloaded word before). The link should be located first and then the problem should be solved.

  1. First use Postman to download or export the file, if it cannot be opened, then look for the problem in the backend code, otherwise locate the frontend call
  2. If the local file on the server cannot be opened, look for the problem in the generated code, otherwise locate the download interface

Guess you like

Origin blog.csdn.net/qq_43961619/article/details/129180490