一、原始方式
使用Apache Commons FileUpload,是apache提供的一个库,支持从HttpServletRequest中解析文件上传数据
1、导入文件上传的两个依赖:commons-fileupload、commons-io
2、表单entype属性设置为multipart/form-data;method属性为post
表示这个表单要提交的是文件类型
3、文件上传的三个对象
3.1 DiskFileItemFactory工厂对象
entype设置为multipart/form-data;DiskFileItemFactory会将每个表单元素封装成FileItem对象
3.2 ServletFileUpload文件上传解析器对象
文件上传解析器对象调用parseRequest(request)方法,获取存储了所有FileItem对象的List集合,遍历集合得到每个表单元素对象
3.3 FileItem对象
用于表示表单中的元素
3.3.1 判断是否是文件
Boolean isFormField()方法用于判断当前表单元素是否是一个文件,文件返回false
3.3.2 不是文件
getFiledName获取组件的名字,getString获取值。存储进数据库
3.3.3 是文件
- getName获取文件名,拼接文件路径
- 根据路径创建文件对象
- write(File file)将读取的文件写入指定的文件
- 在过程前后插入细节操作:
比如避免文件名重复:
String fileName = fileItem.getName();
//为避免和已经存在的文件冲突,将文件名拼接,使名字不会重复
fileName = System.currentTimeMillis()+fileName;
String path = request.getServletContext().getRealPath("/upload/" + fileName);
判断父级路径(/upload/)是否存在
//构建文件
File file = new File(path);
//确保文件的父级目录文件夹存在(存在什么也不做,不存在就创建)
file.getParentFile().mkdirs();
//创建文件
file.createNewFile();
4、完整过程
@WebServlet("/TUploadServlet")
public class TUploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
//1、创建工厂
DiskFileItemFactory dff = new DiskFileItemFactory();
//2、创建文件上传解析器
ServletFileUpload sf = new ServletFileUpload(dff);
//设置上传解析器编码
sf.setHeaderEncoding("UTF-8");
//3、将request对象获取到的数据转化为FileItem
try {
List<FileItem> fileItems = sf.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()){
//普通文件
System.out.println(fileItem.getFieldName() + ":" + fileItem.getString("utf-8"));
} else {
//文件处理逻辑
//4、创建文件上传路径
//4.1 拼接完整的文件目录
String fileName = fileItem.getName();
//为避免和已经存在的文件冲突,将文件名拼接,使名字不会重复
fileName = System.currentTimeMillis()+fileName;
String path = request.getServletContext().getRealPath("/upload/" + fileName);
//构建文件
File file = new File(path);
//确保文件的父级目录文件夹存在(存在什么也不做,不存在就创建)
file.getParentFile().mkdirs();
//创建文件
file.createNewFile();
//将读取到的文件流写入到指定的这个文件中去
fileItem.write(file);
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
二、Servlet API注解简化
1、导入文件上传的两个依赖:commons-fileupload、commons-io
2、表单entype属性设置为multipart/form-data;method属性为post
3、Servlet加注解@MultipartConfig
4、做文件上传
4.1 通过getPart()
方法获取文件
<input type="file" name="file"/>
Part part = request.getPart("file");
4.2 通过getSubmittedFileName
方法获取文件名
String fileName = part.getSubmittedFileName();
4.3 拼接存储路径
String path = request.getServletContext().getRealPath("/upload/"+fileName);
4.4 part对象调write方法写入文件
5、完整过程
@WebServlet("/MyFileServlet")
@MultipartConfig
public class MyFileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置编码
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//普通表单组件
String name = request.getParameter("name");
//获取表单的文件
Part part = request.getPart("file");
//获取文件名
String fileName = part.getSubmittedFileName();
String path = request.getServletContext().getRealPath("/upload/"+fileName);
part.write(path);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
三、SpringMVC通过JS文件上传
1、导入文件上传的两个依赖:commons-fileupload、commons-io
2、在dispatch-servlet中配置文件上传解析器
<!-- 注入文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"/>
<!-- 注入上传的文件最大是多少,一般都是100mb -->
<property name="maxUploadSize" value="1000000"/>
</bean>
3、表单entype属性设置为multipart/form-data;method属性为post
4、在js中获取上传的图片
- 给
<input type="file">
添加一个改变事件,用于获取页面选择的文件,当选择了图片的时候就会触发 - 在data数据模型内定义一个file作为全局变量;在getFile方法内接收文件对象,在提交事件中封装文件对象。
- 将表单的数据封装进FormData对象,发送请求携带FormData对象
<div align="center" id="mainvue">
<form enctype="multipart/form-data" method="post">
用户:<input type="text" name="uname" v-model="uname"><br>
头像:<input type="file" name="pic" v-on:change="getFile($event)"><br>
<input type="button" value="提交" v-on:click="submit()" >
</form>
</div>
new Vue({
el:'#mainvue',
data:{
uname:'',
file:''
},
methods:{
getFile(event){
this.file=event.target.files[0];
},
submit(){
var formData = new FormData();
formData.append("uname", this.uname);
formData.append("pic", this.file);
console.log("append成功")
axios.post("http://localhost:8080/prjspringmvc_js_fileupload_war_exploded/upload.do", formData).then(res=>{
console.log(res.data);
})
}
}
})
5、后端接收
- 控制方法的参数名要与表单组件的name一致,文件用MultipartFile对象接收
- getOriginalFilename():获取文件名称
- transferTo(File file):将接收的文件写入指定的文件
封装进实体类对象也是如此,注意属性名与表单组件name一致
@RequestMapping("/upload")
public String upload(MultipartFile pic, String uname, HttpServletRequest request){
System.out.println("文件上传开始");
//isEmpty为true表示没有文件
if (pic!=null&&!pic.isEmpty()){
System.out.println("用户名:"+uname);
//1、参数已经接收到了文件
//2、获取文件名,拼接存储路径
String fileName = pic.getOriginalFilename();
String path = request.getServletContext().getRealPath("/upload/"+fileName);
//3、创建目标文件
File file = new File(path);
file.getParentFile().mkdirs();
try {
pic.transferTo(file);
System.out.println("上传成功");
return "1";
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return "0";
}
四、文件下载
1、步骤
- 获取前端传过来的要获取的文件名,拼接文件路径
<a href="download.do?fileName=haisi.jpg">图片下载</a>
- 根据路径创建要下载的文件对象
- 设置响应头:响应方式为以附件的形式,并设置响应文件名为下载的文件名,否则下载的文件名就是链接的最后一部分,这里是download.do
- 设置响应的内容类型为可下载的文件
setContentType
- 流的对拷:
通过文件对象获取输入流对象,可以用缓冲流包装
通过response获取输出流对象,循环从输入流读取,从输出流写出
2、完整代码
@RequestMapping("/download")
public String download(String fileName, HttpServletRequest request, HttpServletResponse response){
//1、拼接要下载的文件路径
String path = request.getServletContext().getRealPath("/upload/" + fileName);
System.out.println(path);
//2、创建要下载的文件对象
File file = new File(path);
if (file.exists()){
//3、设置响应方式:以附件的形式处理响应内容,必须设置响应文件名,否则就是链接的最后一部分(download.do)
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
//4、设置响应内容类型为一个可下载的文件
response.setContentType("application/x-msdownload");
try {
//5、流的对拷
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[1024];
int len=0;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.flush();
in.close();
out.close();
System.out.println("下载成功!");
return "1";
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
System.out.println("文件不存在,下载失败");
}
return "0";
}