Scene description

Use Springboot to implement a file download function, the code is as follows

String fileName = "template.xls";
res.setHeader("Content-disposition"."attachment; fileName=" + fileName);
res.setContentType("application/vnd.ms-excel; charset=UTF-8");
res.setCharacterEncoding("UTF-8");
File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "excelTemplate/template.xls");
FileInputStream input = new FileInputStream(file);
OutputStream out = res.getOutputStream();
byte[] b = new byte[2048];
int len;
while((len = input.read(b)) ! = -1) { out.write(b, 0, len); } input.close();Copy the code

The downloaded file is placed under Resources, and when local IDEA is used to start debugging test, the file can be successfully downloaded to the local, and the file can be opened normally.

Error message

The local debugging is completed, the project is packaged into jar package, and then deployed to the server for running. At this time, visit the download link again and get a damaged file with a size of 0KB. Check the server application log and get the following error message; Template.xls cannot be resolved to absolute file path because it does not reside in the file system.

why

After data query, it is found that the problem occurs in the resourceutils.getFile () method, went to the source of this method, found the location of printing the above error message

if (!"file".equals(resourceUrl.getProtocol())) {
    throw new FileNotFoundException(description + " cannot be resolved to absolute file path because it does not reside in the file system: " + resourceUrl);
}
Copy the code

As you can see, this error occurs if the protocol of the current file is not of type file. The file exists as a file in the debugging environment, so you can use resourceutils.getFile () to access, and the jar package after packaging, the file form no longer exists, but can only be read in stream mode.

The solution

ClassPathResource classPathResource = new ClassPathResource("excelTemplate/template.xls");
InputStream input = classPathResource.getInputStream();
Copy the code

Simply read the resourceutils.getFile () method and change it to read by ClassPathResource. Note that the Url does not need the classpath: prefix.

Please point out any mistakes