前言
文件上传在web开发中很多地方都会用到,如用户头像上传,商品图片上传。文件上传的请求的 content-type 必须为 multipart/form-data
请求内容
SpringMVC处理
SpringMVC中提供了两种文件解析器,CommonsMultipartResolver 和 StandardServletMultipartResolver。
示例
@GetMapping("testFileUpload1")
public void testFileUload1(MultipartFile file) {
System.out.println(file);
}
CommonsMultipartResolver
这种方式依赖于Apache的fileupload组件
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
简单源码如下
public class CommonsMultipartResolver extends CommonsFileUploadSupport
implements MultipartResolver, ServletContextAware {
private boolean resolveLazily = false;
}
public abstract class CommonsFileUploadSupport {
protected final Log logger = LogFactory.getLog(getClass());
private final DiskFileItemFactory fileItemFactory;
private final FileUpload fileUpload;
private boolean uploadTempDirSpecified = false;
private boolean preserveFilename = false;
}
核心为FileUpload类,将请求内容解析为一个包含文件名称和文件内容的对象。
StandardServletMultipartResolver
Servlet3.0对文件上传提供了支持
public interface HttpServletRequest extends ServletRequest {
/**
* 获取文件
*/
public Part getPart(String name) throws IOException,
ServletException;
/**
* 获取一个请求上传的所有文件
*/
public Collection<Part> getParts() throws IOException,
ServletException;
}
Tomcat中对文件上传的实现
/**
* Wrapper object for the Coyote request.
*
* @author Remy Maucherat
* @author Craig R. McClanahan
*/
public class Request implements HttpServletRequest {
/**
* {@inheritDoc}
*/
@Override
public Collection<Part> getParts() throws IOException, IllegalStateException,
ServletException {
parseParts(true);
if (partsParseException != null) {
if (partsParseException instanceof IOException) {
throw (IOException) partsParseException;
} else if (partsParseException instanceof IllegalStateException) {
throw (IllegalStateException) partsParseException;
} else if (partsParseException instanceof ServletException) {
throw (ServletException) partsParseException;
}
}
return parts;
}
// 解析出文件内容
private void parseParts(boolean explicit) {
// Create a new file upload handler
DiskFileItemFactory factory = new DiskFileItemFactory();
try {
factory.setRepository(location.getCanonicalFile());
} catch (IOException ioe) {
parameters.setParseFailedReason(FailReason.IO_ERROR);
partsParseException = ioe;
return;
}
factory.setSizeThreshold(mce.getFileSizeThreshold());
ServletFileUpload upload = new ServletFileUpload();
upload.setFileItemFactory(factory);
upload.setFileSizeMax(mce.getMaxFileSize());
upload.setSizeMax(mce.getMaxRequestSize());
parts = new ArrayList<>();
try {
List<FileItem> items =
upload.parseRequest(new ServletRequestContext(this));
int maxPostSize = getConnector().getMaxPostSize();
int postSize = 0;
Charset charset = getCharset();
for (FileItem item : items) {
ApplicationPart part = new ApplicationPart(item, location);
parts.add(part);
}
}
}
}
Tomcat中对文件上传的实现就是参考的Apache的commons-fileupload组件
SpringBoot默认使用的StandardServletMultipartResolver来处理文件上传