文件上传有很多种方式,下面就来看看springmvc是如何进行文件上传的.
使用spring接口MultipartFile
- 添加jar包:
添加下面依赖就可以引入上面jar:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
- 配置上传文件解析器:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置文件编码格式 -->
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 设置最大上传大小 -->
<property name="maxUploadSize" value="10485760"></property>
</bean>
MultipartResolver用于处理文件上传,当收到请求时DispatcherServlet的 checkMultipart() 方法会调用 MultipartResolver 的 isMultipart() 方法判断请求中是否包含文件。如果请求数据中包含文件,则调用 MultipartResolver 的 resolveMultipart() 方法对请求的数据进行解析,然后将文件数据解析成 MultipartFile 并封装在 MultipartHttpServletRequest (继承了 HttpServletRequest) 对象中,最后传递给 Controller,在 MultipartResolver 接口中有如下方法:
- boolean isMultipart(HttpServletRequest request); // 是否是 multipart
- MultipartHttpServletRequest resolveMultipart(HttpServletRequest
request); // 解析请求
- void cleanupMultipart(MultipartHttpServletRequest request);
MultipartFile 封装了请求数据中的文件,此时这个文件存储在内存中或临时的磁盘文件中,需要将其转存到一个合适的位置,因为请求结束后临时存储将被清空。在 MultipartFile 接口中有如下方法:
- String getName(); // 获取参数的名称
- String getOriginalFilename(); // 获取文件的原名称
- String getContentType(); // 文件内容的类型
- boolean isEmpty(); // 文件是否为空
- long getSize(); // 文件大小
- byte[] getBytes(); // 将文件内容以字节数组的形式返回
- InputStream getInputStream(); // 将文件内容以输入流的形式返回
- void transferTo(File dest); // 将文件内容传输到指定文件中
- 处理方法:
@RequestMapping("/uploadByForm.do")
public String uploadByForm(MultipartFile file,HttpServletRequest request,Model model) throws IllegalStateException, IOException{
if(!file.isEmpty()){
//原文件名
String originalFileName = file.getOriginalFilename();
System.out.println("文件名:"+file.getOriginalFilename()+",文件大小:"+file.getSize());
//获取项目根目录文件夹下 fileupload 子文件夹
String ctxPath = request.getServletContext().getRealPath("/fileupload/");
System.out.println(ctxPath);
//获取文件后缀
String extName = originalFileName .substring(originalFileName .lastIndexOf("."));
//上传后的文件名
String fileName = new Date().getTime() + extName;
//将新文件名传回前台
model.addAttribute("fileName",fileName);
//文件按路径
File filePath = new File(ctxPath,fileName);
if(!filePath.getParentFile().exists()){
//如果文件夹不存在就新建一个
filePath.getParentFile().mkdirs();
}
//将文件上传到指定文件夹下
file.transferTo(filePath);
}
return "success";
}
- 在运行的工程根目录下创建fileupload文件夹用于存放上传的文件,我使用的是tomcat服务器,所以上传的文件放在了 tomcat安装路径/webapps/工程/fileupload 下面。
- 重新生成了文件名,并将之传回前台,在前台页面可以根据这个文件名取工程目录中访问这个文件,以达到实时上传显示的目的。
- 上产文件页面:
<h2>使用form表单上传文件</h2>
<form action="uploadByForm.do" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<button type="submit">upload</button>
</form>
必须设置 enctype=”multipart/form-data” 以二进制的方式传输数据
- 上传文件
- 上传成功后跳转页面:
<h2>接收到的后台传过来的文件名为:${fileName}</h2>
<img alt="" src="<%=request.getContextPath()%>/fileupload/${fileName}">
使用输入输出流
@RequestMapping("/uploadByForm.do")
public String uploadByForm(MultipartFile file,HttpServletRequest request,Model model) throws IllegalStateException, IOException{
if(!file.isEmpty()){
//原文件名
String originalFileName = file.getOriginalFilename();
System.out.println("文件名:"+file.getOriginalFilename()+",文件大小:"+file.getSize());
//获取项目根目录文件夹下 fileupload 子文件夹
// String ctxPath = request.getServletContext().getRealPath("/fileupload/");
// System.out.println(ctxPath);
//存放文件目录
String path = "F:/upload/";
//获取文件后缀
String extName = originalFileName .substring(originalFileName .lastIndexOf("."));
//上传后的文件名
String fileName = new Date().getTime() + extName;
//将新文件名传回前台
model.addAttribute("fileName",fileName);
//文件按路径
File filePath = new File(path,fileName);
if(!filePath.getParentFile().exists()){
//如果文件夹不存在就新建一个
filePath.getParentFile().mkdirs();
}
InputStream in = file.getInputStream();
OutputStream out = new FileOutputStream(filePath);
byte[] b = new byte[1024];
int i = 0;
while((i=in.read(b)) != -1){
out.write(b, 0, i);//将字节数组b从下标为0到下标为i的内容写到输出流中
}
out.flush();
out.close();
in.close();
}
return "success";
}
使用ajax上传文件:
- jsp文件
<h2>使用ajax上传文件</h2>
<form enctype="multipart/form-data" id="uploadForm">
<input type="file" id="file" name="file">
<button type="button" id="upload">upload</button>
</form>
<p></p>
- js部分
$(function() {
$('#upload').click(function() {
var form = new FormData($('#uploadForm')[0]);
$.ajax({
type : "POST",
url : "uploadByAjax.do",
data : form,
// 下面三个参数要指定,如果不指定,会报一个JQuery的错误
cache : false,
contentType : false,
processData : false,
async : false,
success : function(data) {
$('p').html('上传成功,文件名为:' + data);
}
});
});
});
使用FormData序列化表单数据
需要注意的是:
- 上面将文件从存放到工程目录下,这样做是不对的。
- 一般会在别的地方另外创建一个目录,然后通过配置一个虚拟路径映射到工程目录中,这样我们可以在工程中访问这个资源,也不用担心由于更新应用而导致上传文件丢失的问题。
tomcat的配置虚拟路径方法:
这里我配置的虚拟路径为 - /工程名/fileupload
这样在页面中使用 “<%=request.getContextPath()%>/fileupload/${fileName}” 就可以访问到刚上传的图片了。