零.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; } }