- Notifications
You must be signed in to change notification settings - Fork13
ramostear/Spring-Boot-File-Handling-Tutorial
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
文件上传和下载是Web应用程序比较常用的功能之一,在本章节中,我将以一个简单的案例来讲解在Spring Boot中如何进行文件的上传与下载。在开始正文之前,我们通过一张思维导图来了解一下文件上传与下载的简单流程:
对于文件上传,控制器中对应的上传方法的参数必须是MultipartFile对象,MultipartFile对象可以是一个数组对象,也可以是单个对象,如果是一个数组对象,则可以进行多文件上传;这里我们仅演示单个文件上传,下面的代码展示了文件上传方法的基本结构:
@PostMapping(value ="/upload",consumes =MediaType.MULTIPART_FORM_DATA_VALUE)@ResponseBodypublicStringfileUpload(@RequestParam("file")MultipartFilefile)throwsIOException {returnnull;}
接下来,我们使用FileOutputStream对象将客户端上传的文件写入到磁盘中,并返回**“File is upload successfully”**的提示信息,下面是文件上传完整的代码:
packagecom.ramostear.application.controller;importcom.ramostear.application.model.FileInfo;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;importjavax.annotation.PostConstruct;importjava.io.*;importjava.util.HashMap;importjava.util.Map;/** * @author : ramostear * @date : 2019/3/8 0008-15:35 */@ControllerpublicclassFileController {@Value ("${file.upload.root.dir}" )StringfileUploadRootDir;privatestaticMap<String,FileInfo>fileRepository =newHashMap<>();@PostConstructpublicvoidinitFileRepository(){FileInfofile1 =newFileInfo ().setFileName ("bg1.jpg" );FileInfofile2 =newFileInfo ().setFileName ("bg2.jpg" );FileInfofile3 =newFileInfo ().setFileName ("bg3.jpg" );fileRepository.put (file1.getName (),file1 );fileRepository.put (file2.getName (),file2 );fileRepository.put (file3.getName (),file3 ); }@PostMapping(value ="/upload",consumes =MediaType.MULTIPART_FORM_DATA_VALUE)@ResponseBodypublicStringfileUpload(@RequestParam("file")MultipartFilefile)throwsIOException {FileconvertFile =newFile (fileUploadRootDir+file.getOriginalFilename ());FileOutputStreamfileOutputStream =newFileOutputStream (convertFile );fileOutputStream.write (file.getBytes () );fileOutputStream.close ();FileInfofileInfo =newFileInfo() .setFileName (file.getOriginalFilename());fileRepository.put (fileInfo.getName (),fileInfo);return"File is upload successfully"; }}
fileRepository用于存放已上传文件的索引信息。
在Spring Boot应用程序中,我们可以使用InputStreamResource对象来下载文件,在下载文件的方法中,我们需要通过Response来设置HttpHeander对象的相关属性,如Content-Disposition、Cache-Control、Pragma和Expires等属性。除此之外,还需要指定Response的响应类型。下面的代码给出了文件下载的详细信息:
@GetMapping("/download/{fileName}")@ResponseBodypublicResponseEntity<Object>downloadFile(@PathVariable(name ="fileName")StringfileName)throwsFileNotFoundException {Filefile =newFile (fileUploadRootDir+fileName);InputStreamResourceresource =newInputStreamResource (newFileInputStream (file ) );HttpHeadersheaders =newHttpHeaders();headers.add ("Content-Disposition",String.format("attachment;filename=\"%s",fileName));headers.add ("Cache-Control","no-cache,no-store,must-revalidate" );headers.add ("Pragma","no-cache" );headers.add ("Expires","0" );ResponseEntity<Object>responseEntity =ResponseEntity.ok() .headers (headers ) .contentLength (file.length ()) .contentType(MediaType.parseMediaType ("application/txt" )) .body(resource);returnresponseEntity; }
下面给出的是完整的文件上传和下载的代码:
packagecom.ramostear.application.controller;importcom.ramostear.application.model.FileInfo;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.core.io.InputStreamResource;importorg.springframework.http.HttpHeaders;importorg.springframework.http.HttpStatus;importorg.springframework.http.MediaType;importorg.springframework.http.ResponseEntity;importorg.springframework.stereotype.Controller;importorg.springframework.ui.Model;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;importjavax.annotation.PostConstruct;importjava.io.*;importjava.util.Collection;importjava.util.HashMap;importjava.util.Map;/** * @author : ramostear * @date : 2019/3/8 0008-15:35 */@ControllerpublicclassFileController {@Value ("${file.upload.root.dir}" )StringfileUploadRootDir;privatestaticMap<String,FileInfo>fileRepository =newHashMap<>();@PostConstructpublicvoidinitFileRepository(){FileInfofile1 =newFileInfo ().setFileName ("bg1.jpg" );FileInfofile2 =newFileInfo ().setFileName ("bg2.jpg" );FileInfofile3 =newFileInfo ().setFileName ("bg3.jpg" );fileRepository.put (file1.getName (),file1 );fileRepository.put (file2.getName (),file2 );fileRepository.put (file3.getName (),file3 ); }@GetMapping("/files")publicStringfiles(Modelmodel){Collection<FileInfo>files =fileRepository.values ();model.addAttribute ("data",files );return"files"; }@PostMapping(value ="/upload",consumes =MediaType.MULTIPART_FORM_DATA_VALUE)@ResponseBodypublicStringfileUpload(@RequestParam("file")MultipartFilefile)throwsIOException {FileconvertFile =newFile (fileUploadRootDir+file.getOriginalFilename ());FileOutputStreamfileOutputStream =newFileOutputStream (convertFile );fileOutputStream.write (file.getBytes () );fileOutputStream.close ();FileInfofileInfo =newFileInfo() .setFileName (file.getOriginalFilename());fileRepository.put (fileInfo.getName (),fileInfo);return"File is upload successfully"; }@GetMapping("/download/{fileName}")@ResponseBodypublicResponseEntity<Object>downloadFile(@PathVariable(name ="fileName")StringfileName)throwsFileNotFoundException {Filefile =newFile (fileUploadRootDir+fileName);InputStreamResourceresource =newInputStreamResource (newFileInputStream (file ) );HttpHeadersheaders =newHttpHeaders();headers.add ("Content-Disposition",String.format("attachment;filename=\"%s",fileName));headers.add ("Cache-Control","no-cache,no-store,must-revalidate" );headers.add ("Pragma","no-cache" );headers.add ("Expires","0" );ResponseEntity<Object>responseEntity =ResponseEntity.ok() .headers (headers ) .contentLength (file.length ()) .contentType(MediaType.parseMediaType ("application/txt" )) .body(resource);returnresponseEntity; }}
创建一个文件信息数据模型作为上传文件信息的载体,下面是FileInfo.java的代码:
packagecom.ramostear.application.model;importlombok.Data;importjava.util.Date;/** * @author : ramostear * @date : 2019/3/8 0008-15:25 */@DatapublicclassFileInfo {privateStringname;privateDateuploadTime =newDate();publicFileInfosetFileName(Stringname){this.setName (name );returnthis; }}
下面是本次demo应用程序的pom.xml文件配置清单:
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/><!-- lookup parent from repository--></parent><groupId>com.ramostear</groupId><artifactId>file-handling</artifactId><version>0.0.1-SNAPSHOT</version><name>file-handling</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
注:本次案例使用freemarker模板引擎作为视图模板
application.properties文件主要设置了freemarker的相关属性以及自定义的**file.upload.root.dir **属性:
spring.freemarker.cache=falsespring.freemarker.prefix=spring.freemarker.suffix=.htmlspring.freemarker.enabled=truespring.freemarker.charset=UTF-8spring.freemarker.template-loader-path=classpath:/templates/file.upload.root.dir = C:/work/upload/
file.upload.root.dir自定义属性设置了文件上传的更目录为:C:/work/upload/
在视图文件中,创建了一个form表单用于上传文件,另外还创建了一个已上传文件列表,提供文件下载操作。
文件上传表单:
文件下载列表:
说明:文件上使用的是异步上传方式进行上传,没有使用同步提交form表单的方式进行
文件上传异步操作代码如下:
$("#upload").on("click",function(){varfileObj=document.getElementById("file").files[0];varform=newFormData();form.append("file",fileObj);varxhr=newXMLHttpRequest();xhr.open("post","http://localhost:8080/upload",true);xhr.onload=function(event){alert(event.currentTarget.responseText);window.location.href=window.location.href;};xhr.send(form);});
使用Maven命令对应用程序进行打包,下面是maven打包的命令:
mvn clean install
在控制台窗口中运行上述命令,等待maven打包。若控制台中显示**“BUILD SUCCESS”**信息,你可以在当前工程目录下的target文件夹中找到相应的JAR文件。
现在,你可以使用下面的命令来运行JAR文件:
java -jar YOUR_JARFILE_NAME
JAR文件成功启动后,你可以在控制台窗口中看到如下的信息:
打开浏览器并在地址栏输入:http://localhost:8080/files 。下面是成功请求后的浏览器截图:
接下来,点击其中任意一个download按钮,测试文件下载功能是否正常:
最后,我们测试一下文件上传功能是否正常。在进行测试之前,我们先看一下文件上传目录中存储的文件信息:
接下来,我们选择一份需要上传的文件,然后点击upload按钮上传文件:
此时,文件以及上传成功,我们再次观察文件上传目录中的文件信息,以验证文件是否成功写入磁盘:
处理本章节的教程内容外,你还可以访问我的个人博客RT社圈的Spring Boot 2.0系列专栏文章阅读更多的教程内容。
本文作者ramostear, 原文标题:Spring Boot(十一)— 文件上传和下载.原文链接:https://www.ramostear.com/posts/2019-03-08/file-handling.html如需转载,请联系本文作者。
About
Spring Boot 文件上传与下载教程源码
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors2
Uh oh!
There was an error while loading.Please reload this page.








