创建新项目:
- Group Id:cn.tedu.spring
- Artifact Id:SPRINGMVC-03-UPLOAD
- Packaging:war
然后,按照传统方式完成项目的创建(添加web.xml;添加Tomcat Runtime,复制pom.xml中的依赖,复制web.xml中的配置,复制spring的配置文件。注意:检查spring的配置文件是否存在多余且不可用的配置,如果有,则删除)。
上传文件的页面只要求是html页面即可,不需要是jsp页面(可以使用jsp页面)。
上传使用的控件是:
并且,上传时的表单必须配置`enctype`属性,并且请求类型必须是`post`类型:
整体设计可以是:
基于SpringMVC的文件上传
基于SpringMVC的文件上传需要添加`spring-webmvc`依赖,并添加`commons-fileupload`依赖:
commons-fileupload
commons-fileupload
1.4
在spring的配置文件中添加:
注意:此项配置中,`
该`
此次项目中,需要开启注解驱动:
创建控制器类`cn.tedu.spring.FileUploadController`,并添加处理请求的方法:
@Controller
public class FileUploadController {
@RequestMapping("/upload.do")
public String handleUpload(
@RequestParam("file") MultipartFile file) {
return null;
}
}
注意:客户端提交的上传的文件需要声明为`MultipartFile`类型(这是一个接口类型,实际类型是`CommonsMultipartFile`),并且,需要添加`@RequestParam`注解,如果没有添加该注解,在某些版本中可能会出错。
当然,以上控制器的方法确定后,前端页面中`:
在控制器中,处理请求的方法中的参数`MultipartFile`其实就是客户选择上传的文件,直接调用`transferTo()`方法将其保存到某个文件即可:
@RequestMapping("/upload.do")
public String handleUpload(
@RequestParam("file") MultipartFile file)
throws IllegalStateException, IOException {
File dest = new File("d:/12345.png");
file.transferTo(dest);
return null;
}
在处理请求的方法中添加参数`HttpServletRequest`,然后调用该参数对象的`getServletContext().getRealPath("upload")`即可获取到`webapp`下的名为`upload`的文件夹的实际路径,例如`D:\apache-tomcat-7.0.54\wtpwebapps\SPRINGMVC-03-UPLOAD\upload\`。
因为上传的文件大多后续将需要通过http方式被访问,所以,上传文件夹是应该在`webapp`之下!则应该通过以上方式获取文件夹的位置。
如果同一个项目中,上传的所有文件都将在同一个文件夹中,则需要保证每个文件的文件名是不相同的,否则,将会出现后续上传的文件会覆盖前序上传的文件!
如果要保证文件名是唯一的,可以使用UUID,也可以使用System.nanoTime(),或使用时间与随机数的组合等等多种方式!
通常,上传的文件的扩展名还是由原文件来决定,即上传过程中,不改变文件的扩展名,通过`MultipartFile`的`getOriginalFilename()`方法可以获取上传的文件的原名(该文件在客户端计算机中的原始名称),然后通过String类的API即可获取文件的扩展名:
String originalFilename = file.getOriginalFilename();
int beginIndex = originalFilename.lastIndexOf(".");
String suffix = "";
if (beginIndex > 0) {
suffix = originalFilename.substring(beginIndex);
}
- `String getOriginalFilename()`:获取原文件名,即文件在客户端计算机中的名称;
- `boolean isEmpty()`:判断上传的文件是否为空,如果在上传表单中没有选中文件,或选中的文件没有内容(0字节),将视为空,则返回true,否则返回false;
- `long getSize()`:获取上传的文件的大小,以字节为单位,可以用于限制上传的文件的大小;
- `String getContentType()`:获取上传的文件的文档类型,其值是文件的MIME类型,可以用于限制上传的文件的类型;
- `InputStream getInputStream()`:获取上传的文件的输入流,主要用于自定义存储文件的过程,当自定义存储时,就不再需要调用`transferTo()`方法了;
- `void transferTo(File dest)`:将上传的文件存储为指定的文件。
在Spring的配置文件中,配置`CommonsMultipartResolver`时,可以为某些属性注入值,来完成某些配置:
- `maxUploadSize`:最大上传尺寸,以字节为单位,假设设置值为10M,则无论一次性上传多少个文件,其总和不允许超过10M;
- `maxUploadSizePerFile`:上传的每个文件的最大尺寸,以字节为单位,假设设置值是10M,如果一次上传多个文件,则每个文件的大小都不可以超过10M,但是,多个文件的总和是可以超过10M的;
- `defaultEncoding`:默认编码。
在商城的案例中
@RequestMapping("/change_avatar")
public ResponseResult changeAvatar(HttpServletRequest request,@RequestParam("file")MultipartFile file){
if (file.isEmpty()) {
throw new FileEmptyException("空白文件异常");
}
if (!UPLOAD_CONTENT_TYPE.contains(file.getContentType())) {
throw new FileContentTypeException("文件格式异常");
}
if (UPLOAD_MAX_SIZE0) {
suffix=Originalfilename.substring(beginIndex);
}
//确定文件名:uuid/nanoTime/..
String filename=System.nanoTime()+suffix;
//创建dest对象new File(parent, filename);
File dest=new File(parent, filename);
//执行上传
try {
file.transferTo(dest);
} catch (IllegalStateException e) {
e.printStackTrace();
throw new FileIllegalstateException("数据异常");
} catch (IOException e) {
e.printStackTrace();
throw new FileIOException("数据异常");
}
//获取uid:getUidFromSession
Integer uid=getuidFromSession(request.getSession());
//生成avatar:/UPLOAD_DIR/文件名.扩展名
String avatar="/"+UPLOAD_DIR+"/"+filename;
//执行更新:userService.changeAvatar(uid,avatar);
userservice.changAvatar(uid, avatar);
//返回成功
return new ResponseResult<>(SUCCESS,avatar);
}