Spring RestController返回ByteArrayResource报错文件找不到求助
解决Spring RestController文件下载的两个核心问题
看起来你遇到的是Spring文件下载里两个非常典型的坑:一是@RestController默认把返回对象序列化JSON了,二是ByteArrayResource本身没有实际URL,调用getURL()肯定报错。我来一步步帮你解决:
问题根源拆解
- 下载内容变成JSON:
@RestController自带@ResponseBody注解,会自动把你返回的ByteArrayResource对象序列化成JSON字符串,所以你看到了{"byteArray":"JVBERi0xLjQKJeL...."}这种格式,而不是实际的文件流。 - FileNotFoundException:
ByteArrayResource是内存中的字节数组资源,根本没有对应的文件系统URL,所以调用它的getURL()方法必然抛出这个异常,你的代码里大概率有地方尝试获取这个资源的URL,得去掉。
正确的实现方式
用ResponseEntity<Resource>来手动构建下载响应,完全掌控响应头和返回体,避开@RestController的自动序列化。下面是修正后的完整代码示例:
@Api("products") @RestController @RequestMapping("/v1/products") public class ProductController { @GetMapping("/download/{id}") public ResponseEntity<Resource> downloadFile(@PathVariable Long id) throws IOException { // 1. 替换成你的实际业务逻辑:从数据库/存储服务获取文件字节数组 byte[] fileContent = fetchFileBytesById(id); // 2. 包装成ByteArrayResource ByteArrayResource resource = new ByteArrayResource(fileContent); // 3. 构建响应,设置正确的头信息 return ResponseEntity.ok() // 根据文件类型设置ContentType,比如PDF用application/pdf,通用文件用application/octet-stream .contentType(MediaType.APPLICATION_PDF) // 设置下载头:attachment触发浏览器下载,filename指定下载后的文件名 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"product-document.pdf\"") // 直接返回资源对象,Spring会自动读取输入流写入响应 .body(resource); } // 模拟获取文件字节数组的业务方法 private byte[] fetchFileBytesById(Long id) { // 这里替换成你的实际逻辑:比如从数据库Blob字段读取,或者从OSS下载 return new byte[0]; } }
关键注意事项
- 不要调用
resource.getURL():ByteArrayResource是内存资源,没有物理URL路径,完全不需要这个操作。 - 匹配正确的ContentType:如果是Excel文件,用
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;Word文档用application/vnd.openxmlformats-officedocument.wordprocessingml.document;如果不确定文件类型,用通用的application/octet-stream。 - Content-Disposition头:如果想让浏览器直接预览文件(比如图片、PDF),可以把
attachment改成inline,但大部分下载场景用attachment更合适。
这样修改后,浏览器会正确触发文件下载,也不会再出现那个FileNotFoundException了。
内容的提问来源于stack exchange,提问作者Aminos
相关产品推荐
相关产品推荐

