零.MultipartFile上传文件的具体实例如下:

http://blog.csdn.net/swingpyzf/article/details/20230865

一.具体类和方法

上传文件主要方法是transferTo(),可以将某个文件复制保存到新的路径中。

Multipart接口的实现类CommonsMultipartFile类,有个保存文件到新路径的方法transferTo(),调用了FileItem接口的方法write(),
FileItem接口的实现类DiskFileItem类

二.MultipartFile接口源码如下:

public interface MultipartFile {
String getName();

//获取文件原名(不包含路径)
String getOriginalFilename();

//获取上传文件的类型
String getContentType(); boolean isEmpty(); long getSize(); byte[] getBytes() throws IOException; InputStream getInputStream() throws IOException;

//保存到一个目标文件中
void transferTo(File var1) throws IOException, IllegalStateException;
}

2.MultipartFile接口的实现类CommonsMultipartFile源码如下:

public class CommonsMultipartFile implements MultipartFile, Serializable {
protected static final Log logger = LogFactory.getLog(CommonsMultipartFile.class);
private final FileItem fileItem;
private final long size; public CommonsMultipartFile(FileItem fileItem) {
this.fileItem = fileItem;
this.size = this.fileItem.getSize();
} public final FileItem getFileItem() {
return this.fileItem;
} public String getName() {
return this.fileItem.getFieldName();
} public String getOriginalFilename() {
String filename = this.fileItem.getName();
if(filename == null) {
return "";
} else {
int pos = filename.lastIndexOf("/");
if(pos == -1) {
pos = filename.lastIndexOf("\\");
} return pos != -1?filename.substring(pos + 1):filename;
}
} public String getContentType() {
return this.fileItem.getContentType();
} public boolean isEmpty() {
return this.size == 0L;
} public long getSize() {
return this.size;
} public byte[] getBytes() {
if(!this.isAvailable()) {
throw new IllegalStateException("File has been moved - cannot be read again");
} else {
byte[] bytes = this.fileItem.get();
return bytes != null?bytes:new byte[0];
}
} public InputStream getInputStream() throws IOException {
if(!this.isAvailable()) {
throw new IllegalStateException("File has been moved - cannot be read again");
} else {
InputStream inputStream = this.fileItem.getInputStream();
return (InputStream)(inputStream != null?inputStream:new ByteArrayInputStream(new byte[0]));
}
} public void transferTo(File dest) throws IOException, IllegalStateException {
if(!this.isAvailable()) {
throw new IllegalStateException("File has already been moved - cannot be transferred again");
} else if(dest.exists() && !dest.delete()) {
throw new IOException("Destination file [" + dest.getAbsolutePath() + "] already exists and could not be deleted");
} else {
try {
this.fileItem.write(dest);
if(logger.isDebugEnabled()) {
String ex = "transferred";
if(!this.fileItem.isInMemory()) {
ex = this.isAvailable()?"copied":"moved";
} logger.debug("Multipart file \'" + this.getName() + "\' with original filename [" + this.getOriginalFilename() + "], stored " + this.getStorageDescription() + ": " + ex + " to [" + dest.getAbsolutePath() + "]");
} } catch (FileUploadException var3) {
throw new IllegalStateException(var3.getMessage());
} catch (IOException var4) {
throw var4;
} catch (Exception var5) {
logger.error("Could not transfer to file", var5);
throw new IOException("Could not transfer to file: " + var5.getMessage());
}
}
} protected boolean isAvailable() {
return this.fileItem.isInMemory()?true:(this.fileItem instanceof DiskFileItem?((DiskFileItem)this.fileItem).getStoreLocation().exists():this.fileItem.getSize() == this.size);
} public String getStorageDescription() {
return this.fileItem.isInMemory()?"in memory":(this.fileItem instanceof DiskFileItem?"at [" + ((DiskFileItem)this.fileItem).getStoreLocation().getAbsolutePath() + "]":"on disk");
}
}

三.FileItem接口,具体的api介绍如以下链接:

http://www.jb51.net/article/90331.htm

1.  boolean isFormField()
isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果是普通表单字段则返回true,否则返回false。因此,可以使用该方法判断是否为普通表单域,还是文件上传表单域。
2.  String getName()
getName方法用于获得文件上传字段中的文件名。
注意IE或FireFox中获取的文件名是不一样的,IE中是绝对路径,FireFox中只是文件名。
3.  String getFieldName()
getFieldName方法用于返回表单标签name属性的值。如上例中<input type="text" name="column" />的value。
4.  void write(File file)
write方法用于将FileItem对象中保存的主体内容保存到某个指定的文件中。如果FileItem对象中的主体内容是保存在某个临时文件中,该方法顺利完成后,临时文件有可能会被清除。该方法也可将普通表单字段内容写入到一个文件中,但它主要用途是将上传的文件内容保存在本地文件系统中。
5.  String getString()
getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回,它有两个重载的定义形式:
public java.lang.String getString()
public java.lang.String getString(java.lang.String encoding)
throws java.io.UnsupportedEncodingException
前者使用缺省的字符集编码将主体内容转换成字符串,后者使用参数指定的字符集编码将主体内容转换成字符串。如果在读取普通表单字段元素的内容时出现了中文乱码现象,请调用第二个getString方法,并为之传递正确的字符集编码名称。
6.  String getContentType()
getContentType 方法用于获得上传文件的类型,即表单字段元素描述头属性“Content-Type”的值,如“image/jpeg”。如果FileItem类对象对应的是普通表单字段,该方法将返回null。
7.  boolean isInMemory()
isInMemory方法用来判断FileItem对象封装的数据内容是存储在内存中,还是存储在临时文件中,如果存储在内存中则返回true,否则返回false。
8.  void delete()
delete方法用来清空FileItem类对象中存放的主体内容,如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
尽管当FileItem对象被垃圾收集器收集时会自动清除临时文件,但及时调用delete方法可以更早的清除临时文件,释放系统存储资源。另外,当系统出现异常时,仍有可能造成有的临时文件被永久保存在了硬盘中。
9.  InputStream getInputStream()
以流的形式返回上传文件的数据内容。
10. long getSize()
返回该上传文件的大小(以字节为单位)。

四.FileItem的实现类DiskFileItem源码如下:

重点看write()方法。

public class DiskFileItem implements FileItem {
private static final long serialVersionUID = 2237570099615271025L;
public static final String DEFAULT_CHARSET = "ISO-8859-1";
private static final String UID = UUID.randomUUID().toString().replace('-', '_');
private static final AtomicInteger COUNTER = new AtomicInteger(0);
private String fieldName;
private final String contentType;
private boolean isFormField;
private final String fileName;
private long size = -1L;
private final int sizeThreshold;
private final File repository;
private byte[] cachedContent;
private transient DeferredFileOutputStream dfos;
private transient File tempFile;
private File dfosFile;
private FileItemHeaders headers; public DiskFileItem(String fieldName, String contentType, boolean isFormField, String fileName, int sizeThreshold, File repository) {
this.fieldName = fieldName;
this.contentType = contentType;
this.isFormField = isFormField;
this.fileName = fileName;
this.sizeThreshold = sizeThreshold;
this.repository = repository;
} public InputStream getInputStream() throws IOException {
if(!this.isInMemory()) {
return new FileInputStream(this.dfos.getFile());
} else {
if(this.cachedContent == null) {
this.cachedContent = this.dfos.getData();
} return new ByteArrayInputStream(this.cachedContent);
}
} public String getContentType() {
return this.contentType;
} public String getCharSet() {
ParameterParser parser = new ParameterParser();
parser.setLowerCaseNames(true);
Map params = parser.parse(this.getContentType(), ';');
return (String)params.get("charset");
} public String getName() {
return Streams.checkFileName(this.fileName);
} public boolean isInMemory() {
return this.cachedContent != null?true:this.dfos.isInMemory();
} public long getSize() {
return this.size >= 0L?this.size:(this.cachedContent != null?(long)this.cachedContent.length:(this.dfos.isInMemory()?(long)this.dfos.getData().length:this.dfos.getFile().length()));
} public byte[] get() {
if(this.isInMemory()) {
if(this.cachedContent == null) {
this.cachedContent = this.dfos.getData();
} return this.cachedContent;
} else {
byte[] fileData = new byte[(int)this.getSize()];
BufferedInputStream fis = null; try {
fis = new BufferedInputStream(new FileInputStream(this.dfos.getFile()));
fis.read(fileData);
} catch (IOException var12) {
fileData = null;
} finally {
if(fis != null) {
try {
fis.close();
} catch (IOException var11) {
;
}
} } return fileData;
}
} public String getString(String charset) throws UnsupportedEncodingException {
return new String(this.get(), charset);
} public String getString() {
byte[] rawdata = this.get();
String charset = this.getCharSet();
if(charset == null) {
charset = "ISO-8859-1";
} try {
return new String(rawdata, charset);
} catch (UnsupportedEncodingException var4) {
return new String(rawdata);
}
} public void write(File file) throws Exception {
if(this.isInMemory()) {
FileOutputStream outputFile = null; try {
outputFile = new FileOutputStream(file);
outputFile.write(this.get());
} finally {
if(outputFile != null) {
outputFile.close();
} }
} else {
File outputFile1 = this.getStoreLocation();
if(outputFile1 == null) {
throw new FileUploadException("Cannot write uploaded file to disk!");
} this.size = outputFile1.length();
if(!outputFile1.renameTo(file)) {
BufferedInputStream in = null;
BufferedOutputStream out = null; try {
in = new BufferedInputStream(new FileInputStream(outputFile1));
out = new BufferedOutputStream(new FileOutputStream(file));
IOUtils.copy(in, out);
} finally {
if(in != null) {
try {
in.close();
} catch (IOException var19) {
;
}
} if(out != null) {
try {
out.close();
} catch (IOException var18) {
;
}
} }
}
} } public void delete() {
this.cachedContent = null;
File outputFile = this.getStoreLocation();
if(outputFile != null && outputFile.exists()) {
outputFile.delete();
} } public String getFieldName() {
return this.fieldName;
} public void setFieldName(String fieldName) {
this.fieldName = fieldName;
} public boolean isFormField() {
return this.isFormField;
} public void setFormField(boolean state) {
this.isFormField = state;
} public OutputStream getOutputStream() throws IOException {
if(this.dfos == null) {
File outputFile = this.getTempFile();
this.dfos = new DeferredFileOutputStream(this.sizeThreshold, outputFile);
} return this.dfos;
} public File getStoreLocation() {
return this.dfos == null?null:this.dfos.getFile();
} protected void finalize() {
File outputFile = this.dfos.getFile();
if(outputFile != null && outputFile.exists()) {
outputFile.delete();
} } protected File getTempFile() {
if(this.tempFile == null) {
File tempDir = this.repository;
if(tempDir == null) {
tempDir = new File(System.getProperty("java.io.tmpdir"));
} String tempFileName = String.format("upload_%s_%s.tmp", new Object[]{UID, getUniqueId()});
this.tempFile = new File(tempDir, tempFileName);
} return this.tempFile;
} private static String getUniqueId() {
int limit = 100000000;
int current = COUNTER.getAndIncrement();
String id = Integer.toString(current);
if(current < 100000000) {
id = ("00000000" + id).substring(id.length());
} return id;
} public String toString() {
return String.format("name=%s, StoreLocation=%s, size=%s bytes, isFormField=%s, FieldName=%s", new Object[]{this.getName(), this.getStoreLocation(), Long.valueOf(this.getSize()), Boolean.valueOf(this.isFormField()), this.getFieldName()});
} private void writeObject(ObjectOutputStream out) throws IOException {
if(this.dfos.isInMemory()) {
this.cachedContent = this.get();
} else {
this.cachedContent = null;
this.dfosFile = this.dfos.getFile();
} out.defaultWriteObject();
} private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
if(this.repository != null) {
if(!this.repository.isDirectory()) {
throw new IOException(String.format("The repository [%s] is not a directory", new Object[]{this.repository.getAbsolutePath()}));
} if(this.repository.getPath().contains("\u0000")) {
throw new IOException(String.format("The repository [%s] contains a null character", new Object[]{this.repository.getPath()}));
}
} OutputStream output = this.getOutputStream();
if(this.cachedContent != null) {
output.write(this.cachedContent);
} else {
FileInputStream input = new FileInputStream(this.dfosFile);
IOUtils.copy(input, output);
this.dfosFile.delete();
this.dfosFile = null;
} output.close();
this.cachedContent = null;
} public FileItemHeaders getHeaders() {
return this.headers;
} public void setHeaders(FileItemHeaders pHeaders) {
this.headers = pHeaders;
}
}

SpringMVC上传文件的MultipartFile源码的更多相关文章

  1. SpringMVC 上传文件 MultipartFile 转为 File

    在使用 SpringMVC 上传文件时,接收到的文件格式为 MultipartFile,但是在很多场景下使用都需要File格式的文件,记录下以便日后使用. 以下mFile为MultipartFile文 ...

  2. springmvc上传文件,抄别人的

    SpringMVC中的文件上传 分类: SpringMVC 2012-05-17 12:55 26426人阅读 评论(13) 收藏 举报 stringuserinputclassencoding 这是 ...

  3. 2. SpringMVC 上传文件操作

    1.创建java web项目:SpringMVCUploadDownFile 2.在项目的WebRoot下的WEB-INF的lib包下添加如下jar文件 com.springsource.com.mc ...

  4. 使用springMVC上传文件

    control层实现功能: @RequestMapping(value="upload2") public String upLoad2(HttpServletRequest re ...

  5. SpringMVC上传文件总结

    如果是maven项目 需要在pom.xml文件里面引入下面两个jar包 <dependency> <groupId>commons-fileupload</groupId ...

  6. springBoot上传文件时MultipartFile报空问题解决方法

    springBoot上传文件时MultipartFile报空问题解决方法 1.问题描述: 之前用spring MVC,转成spring boot之后发现上传不能用.网上参考说是spring boot已 ...

  7. SpringMVC上传文件(图片)并保存到本地

    SpringMVC上传文件(图片)并保存到本地 小记一波~ 基本的MVC配置就不展示了,这里给出核心代码 在spring-mvc的配置文件中写入如下配置 <bean id="multi ...

  8. springmvc 上传文件时的错误

    使用springmvc上传文件一直失败,文件参数一直为null, 原来是配置文件没写成功. <bean id="multipartResolver" class=" ...

  9. springmvc上传文件报错org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.web.multipart.MultipartFile]

    在用springmvc+mybatis进行项目开发时,上传文件抛异常... org.springframework.beans.BeanInstantiationException: Could no ...

随机推荐

  1. 小峰mybatis(5)mybatis使用注解配置sql映射器--动态sql

    一.使用注解配置映射器 动态sql: 用的并不是很多,了解下: Student.java 实体bean: package com.cy.model; public class Student{ pri ...

  2. 【整理总结】代码沉淀 - CefSharp - 比较流行的第三方内嵌浏览器组件

    .NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework web: https://github.com/ce ...

  3. VS2005常用快捷键

    Visual C++ 2005有很多种快捷键的映射方案,有适合 Emacs 用户的,有适合 Visual C++ 6.0 用户的,也有 Visual Studio 2005的,下面的快捷键符合IDE默 ...

  4. ubuntu 14.04 lamp 安装与配置

    一.安装apache 1.打开终端:Ctrl+Alt+T sudo apt-get update 2.通过apt-get方式安装Apache: sudo apt-get install apache2 ...

  5. html_常用技巧总结

    =============  博客大全: 脚本之家:http://www.jb51.net/list/list_233_104.htm 红黑联盟: http://www.2cto.com/kf/yid ...

  6. Linux下XAMPP装完之后,Navicat无法连上数据库的问题的解决 注意'mypassword'是当前的mysql登录密码

    Linux下装完XAMPP之后,mysql是自带装好了的,这个时候,mysql的root用户没有密码. 在mac 下安装好xampp后,需要在终端命令行操作时,比如输入:mysql -u root - ...

  7. python中__name__的使用

    这几天开始学习Python,遇到一些问题,也解决了一些问题. 其中if __name__ == '__main__':这句估计很多和我一样的初学者都是不求甚解.这里作一下解释: 1:__name__是 ...

  8. Python预编译语句防止SQL注入

    这个月太忙,最近不太太平,我的愿望是世界和平! ================================== 今天也在找python的预编译,早上写的sql是拼接来构成的.于是找了2篇文章,还 ...

  9. Bogart BogartAutoCode.vb

    Imports System.Data.SqlClient Imports System.Data Public Class BogartAutoCodeDataBase Private Conn A ...

  10. 使用再生龙Clonezilla备份还原Linux系统

    一位老哥推荐给我的,产地是祖国宝岛台湾,实测效果非常好,解决了我的一个大问题. 为了减少篇幅,方便阅读,把备份还原的过程单独写一篇随笔. 官网简介:http://clonezilla.nchc.org ...