文件下载的原理就是服务端向客户端返回二进制流和信息,而Springmvc通过ResponseEntity完成。我们在controller中编写以下接口实现下载的功能:
@GetMapping("download/{filename}") public ResponseEntity<byte[]>download(@PathVariable String filename) throws IOException { //下载文件的路径(这里绝对路径) String filepath= "F:/download/"+filename; File file =new File(filepath); //创建字节输入流,这里不实用Buffer类 InputStream in = new FileInputStream(file); //available:获取输入流所读取的文件的最大字节数 byte[] body = new byte[in.available()]; //把字节读取到数组中 in.read(body); //设置请求头 MultiValueMap<String, String> headers = new HttpHeaders(); headers.add("Content-Disposition", "attchement;filename=" + file.getName()); //设置响应状态 HttpStatus statusCode = HttpStatus.OK; in.close(); ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode); return entity;//返回 }这样就是实现了文件下载功能,如果用传统servlet的方式下载文件可能需要在HttpServletResponse response中设置各种信息,而使用Springmvc的ResponseEntity只需要将文件二进制主体、头信息以及状态码设置好即可进行文件下载,在易用性和简洁上更胜一筹。
运行测试打开浏览器输入::8080/index3.html;点击需要下载的文件,就实现了文件下载的功能,运行情况图如下:
此时你就遇到了一个文件下载非常常见的问题:中文文件名错误显示。这个解决方案也很容易解决,只需将Content-Disposition内容后面的文件名进行url编码即可,具体代码为(替换上面对于部分):
headers.add("Content-Disposition", "attchement;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));这样重启程序,刷新页面再次点击下载的链接,你就会发现文件被成功的下载了:
至此,Springmvc的单文件上传、多文件上传以及文件下载你已经全部掌握了,是不是满满的成就感想去实现一个自己的小网站并把相关内容放进去?不过Springmvc文件上传下载虽然简单,但你依然需要掌握其原理,学好java中的io文件传输,这样在各种场景的文件传输任务中方能胜任。
总结前面所讲文件上传,前端就是form表单用<input type="file">表示客户端要上传文件,而服务端主要使用MultipartFile或者MultipartFile[]分别接收单个文件和多个文件。而在存储到本地也仅仅需要在本地磁盘创建对应文件然后MultipartFile调用transferTo()方法即可将上传的文件储存。
而文件下载的前端需要一个请求的url链接,服务端需要编写这个链接对应的接口。通过一些名称找到文件在本地真实的位置通过ResponseEntity即可将二进制文件返回给客户达到文件下载的功能。而ResponseEntity使用也很简单在创建时候只需要传入二进制主体、头和状态码即可成功返回,而这些Springmvc已进行了很好封装你可以直接使用。
而无论是文件上传、多文件上传还是文件下载,一个完整的案例大致都需要这样一个过程:
构思需求和页面大体样式
编写前端html页面
编写服务端响应的请求
启动程序运行测试
在其中过程如果有问题可以根据编译器的错误提示、运行时的错误日志找到根源进行修正,这样完整的案例就可以成功完成啦!
案例拓展你是否觉得自己掌握的可以了?那好,咱们拓展提升一下,我给你来一个需求:单文件和多文件混合上传
假设小明需要实现一个文件上传功能,小明需要上传一份简历和若干份照片(小于3)。这个项目该如何设计呢?它的计划页面可能是这样的: