1.前言
这几天一直在调图片上传的接口,总结一下,想着也该写博客了,就从这篇开始吧。
2.MultipartHttpServletRequest
首先在SpringMVC中,对ServletAPI的HttpServletRequest接口进行了很好的扩展,使得其能够更好地处理文件上传,扩展后的接口名为MultipartHttpServletRequest。
interface MultipartHttpServletRequest extends HttpServletRequest{
public MultipartFile getFile(String name);//获取文件
public Map getFileMap();//获取多个文件,保存在map
public Iterator getFileNames();
}
如上所示:MultipartHttpServletRequest接口简单地扩展了默认的HttpServletRequest接口
3.使用multipart请求
只要发现一个multipart请求,就表明控制器当中存在一个实现了MultipartHttpServletRequest接口的request对象,我们可以通过上面的MultipartHttpServletRequest接口来访问multipart请求中的文件,下面的代码段显示为上传表单:
<form action="upload"enctype="multipart/form-data">
<input type="file" name="myFile"/>
<input type="submit" value="Upload! "/>
</form>
实际上,上传表单只需要满足两点,enctype属性的属性值设置为multipart/form-data,input的type属性的属性值设为file。
enctype属性规定在发送到服务器之前应该如何对表单数据进行编码。
input的type属性是指提交的表单属于文件类型
值 | 描述 |
---|---|
application/x-www-form-urlencoded | 在发送前编码所有字符(默认) |
multipart/form-data | 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。 |
text/plain | 空格转换为 “+” 加号,但不对特殊字符编码。 |
注意:在上面提到的上传文件的input type必须为file,name可以自定义为myFile,name属性的用处是前面提到的getFile方法的参数,即根据name的值来获取文件
4.读取文件
MultipartFile multipartFile = multiRequest.getFile("file");
根据multiRequest的getFile方法获取到的文件类型不是file,而是MultipatFile类型,下面我们看看MultipatFile接口
interface MultipartFile {
public byte[] getBytes();
public String getContentType();
public java.io.InputStream getInputStream();
public String getName();
public String getOriginalFilename();
public long getSize();
public boolean isEmpty();
public void transferTo(java.io.File dest);
}
MultipartFile是spring类型,代表HTML中form data方式上传的文件,包含二进制数据+文件名称,
在MultipartFile接口中定义了如下很多有用的方法。
l 使用getSize()方法获得文件长度,以此决定允许上传的文件大小。
l 使用isEmpty()方法判断上传文件是否为空文件,以此决定是否拒绝空文件。
l 使用getInputStream()方法将文件读取为java.io.InputStream流对象。
l 使用getContentType()方法获得文件类型,以此决定允许上传的文件类型。
l 使用transferTo(dest)方法将上传文件写到服务器上指定的文件。
5.图片上传接口实现
private static final String basePath = "服务器存储图片地址";
private static final String readPath = "读取图片地址";
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;//转换request,获取request中的文件
MultipartFile multipartFile = multiRequest.getFile("file");//获取type name为file的文件
InputStream inputStream = null;
OutputStream outputStream = null;
try{
inputStream = multipartFile.getInputStream();//将文件读取为InputStream流对象
String fileName = multipartFile.getOriginalFilename();//获取文件初始名
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
String reName = UUID.randomUUID().toString() + "." + suffix;
String relativePath ="banner/" +DateUtil.getCurrentDate() + "/" + reName; // 相对路径,即数据库存储的路径
String savePath = basePath +'/'+ relativePath; //处理文件上传的路径
File file = new File(savePath);//根据文件路径创建文件
if (!file.getParentFile().exists()) {//判断其父目录是否存在
boolean result1 = file.getParentFile().mkdirs();//不存在则创建
if (!result1) {
logger.error("Failed to initialize file directory,path=" + file.getParentFile());//初始化文件目录失败
}
}
outputStream = new FileOutputStream(file);//创建该文件的输出流通道
IOUtils.copy(inputStream, outputStream);//将从前台获取到的数据写入该输出流通道当中(即将图片存在服务器当中)
}catch (Exception e){
logger.error("file upload error:", e);
}finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}