深入springMVC源码------文件上传源码解析(下篇)
在上篇《深入springMVC------文件上传源码解析(上篇) 》中,介绍了springmvc文件上传相关。那么本篇呢,将进一步介绍springmvc 上传文件的效率问题。
相信大部分人在处理文件上传逻辑的时候会直接获取输入流直接进行操作,伪代码类似这样:
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResultView upload(@RequestParam("file") MultipartFile file) {
Inputstream in = file.getInputStream();
...
}
但是,出于效率,其实我个人更推荐使用 MultipartFile 的 transferTo 方法进行操作,类似这样:
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResultView upload(@RequestParam("file") MultipartFile file) {
file.transferTo(new File(destFile));
...
}
为什么呢?这个就得从源码说起,废话不多说,咱们直接去看源码吧:
1. 先看 MultipartFile(其实现类CommonsMultipartFile) 的getInputStream方法:
CommonsMultipartFile:
public InputStream getInputStream() throws IOException {
if (!isAvailable()) {
throw new IllegalStateException("File has been moved - cannot be read again");
}
InputStream inputStream = this.fileItem.getInputStream();
return (inputStream != null ? inputStream : new ByteArrayInputStream(new byte[0]));
}
通过源码可以看到,spring是通过commons-fileupload 中的FileItem对象去获取输入流,那么就去看看FileItem(其实现类DiskFileItem)的对应方法:
DiskFileItem:
public InputStream getInputStream()
throws IOException {
if (!isInMemory()) {
return new FileInputStream(dfos.getFile());
} if (cachedContent == null) {
cachedContent = dfos.getData();
}
return new ByteArrayInputStream(cachedContent);
}
通过源码可以看到:先去查看是否存在于内存中,如果存在,就将内存中的file对象包装为文件流, 如果不存在,那么就去看缓存,如果缓存存在就从缓存中获取字节数组并包装为输入流。
接下来,咱们再看看 CommonsMultipartFile 的 transferTo 方法,以便形成比较:
CommonsMultipartFile:
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
if (!isAvailable()) {
throw new IllegalStateException("File has already been moved - cannot be transferred again");
} if (dest.exists() && !dest.delete()) {
throw new IOException(
"Destination file [" + dest.getAbsolutePath() + "] already exists and could not be deleted");
} try {
this.fileItem.write(dest);
if (logger.isDebugEnabled()) {
String action = "transferred";
if (!this.fileItem.isInMemory()) {
action = isAvailable() ? "copied" : "moved";
}
logger.debug("Multipart file '" + getName() + "' with original filename [" +
getOriginalFilename() + "], stored " + getStorageDescription() + ": " +
action + " to [" + dest.getAbsolutePath() + "]");
}
}
catch (FileUploadException ex) {
throw new IllegalStateException(ex.getMessage());
}
catch (IOException ex) {
throw ex;
}
catch (Exception ex) {
logger.error("Could not transfer to file", ex);
throw new IOException("Could not transfer to file: " + ex.getMessage());
}
}
不多说,主要看 this.fileItem.write(dest) 这一句,利用commons-fileupload 中的相关方法:
DiskFileItem:
public void write(File file) throws Exception {
if (isInMemory()) {
FileOutputStream fout = null;
try {
fout = new FileOutputStream(file);
fout.write(get());
} finally {
if (fout != null) {
fout.close();
}
}
} else {
File outputFile = getStoreLocation();
if (outputFile != null) {
// Save the length of the file
size = outputFile.length();
........
通过源码可以看到 transfoTo 方法很干净利落,直接去将内存中的文件通过输出流写出到指定的file 。 等等,跟上面的 getInputStream方法相比,是不是省了点步骤? 是的,再来一张图,清晰地表示两个方法地不同之处:

图中:
红色线表示使用的是transferTo方法,黑色线代表getInputStream方法, 可见,transferTo直接将内存中的文件缓存直接写入到磁盘的物理文件, 而getInputStream方法会中转一次(先通过getInputStream从内存中获取流,再通过outputStream输出到磁盘物理文件)。两者相比,即使从步骤来看,你也能看出来transferTo效率更高了吧。
好啦,本篇就到此结束啦!
深入springMVC源码------文件上传源码解析(下篇)的更多相关文章
- 使用SpringMVC框架实现文件上传和下载功能
使用SpringMVC框架实现文件上传和下载功能 (一)单个文件上传 ①配置文件上传解释器 <!—配置文件上传解释器 --> <mvc:annotation-driven>&l ...
- (转)SpringMVC学习(九)——SpringMVC中实现文件上传
http://blog.csdn.net/yerenyuan_pku/article/details/72511975 这一篇博文主要来总结下SpringMVC中实现文件上传的步骤.但这里我只讲单个文 ...
- SpringMVC+BUI实现文件上传(附详解,源码下载)
中午有限时间写这博文,前言就不必多说了,直奔主题吧. BUI是一个前端框架,关于BUI的介绍请看博主的文章那些年用过的一些前端框架. 下面我们开始实例的讲解! 一.效果演示: 上传成功后,会发现本地相 ...
- ajaxFileUpload 实现多文件上传(源码)
按照原ajaxFileUpload.js是不能多文件上传的.需要对源码进行修改:主要修改了fileElementId部分 具体参考 https://blog.csdn.net/itmyhome1990 ...
- SpringMVC国际化与文件上传
点击阅读上一章 其实SpringMVC中的页面国际化与上一章的验证国际化基本一致. 1.对页面进行国际化 1)首先我们对Spring配置文件中添加国际化bean配置 <!-- 注册国际化信息,必 ...
- SpringMvc commons-fileupload图片/文件上传
简介 SpringMvc文件上传的实现,是由commons-fileupload这个jar包实现的. 需求 在修改商品页面,添加上传商品图片功能. Maven依赖包 pom.xml <!-- 文 ...
- SpringMVC框架06——文件上传与下载
1.文件上传 Spring MVC框架的文件上传是基于commons-fileupload组件的文件上传,只不过Spring MVC框架在原有文件上传组件上做了进一步封装,简化了文件上传的代码实现. ...
- springMVC实现多文件上传
<h2>上传多个文件 实例</h2> <form action="/workreport/uploadMultiFile.html" method=& ...
- SpringMvc入门五----文件上传
知识点: SpringMvc单文件上传 SpringMvc多文件上传 这里我直接演示多文件上传,单文件的上传就不说了,不过代码都是现成的. 效果预览: DEMO图: 添加文件上传j ...
随机推荐
- JAVA泛型详解2 转载
转载地址:http://www.cnblogs.com/sunwei2012/archive/2010/10/08/1845938.html 普通泛型 class Point<T>{ // ...
- android控件的对齐方式(转)
<?xml version="1.0" encoding="utf-8"?> <!-- android:layout_above 将该控件的底 ...
- windows+caffe(七)——ComputeImageMean.bat
1.首先我们使用lmdb数据格式(怎样得到lmdb数据格式,看我的另一篇)求得均值: 新建ComputeImageMean.bat,里面输入: D:/deeptools/caffe-windows-m ...
- 山东省第七届ACM省赛------The Binding of Isaac
The Binding of Isaac Time Limit: 2000MS Memory limit: 65536K 题目描述 Ok, now I will introduce this game ...
- ANGULAR JS WATCH监听使用(详)
ANGULAR 监听使用: 当angular数据模型发生变化时,我们需要如果需要根据他的变化触发其他的事件. $watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你. ...
- 课堂 一些代码的叫法 JavaScript js
():圆括号 {} :花括号 <>:尖括号 [] :方括号
- js中文乱码怎么解决【转】
①.js 文件中文显示乱码Javascript文件XX.js编辑保存时有一种编码方案(如GBK),当打开文件的时候所用的编码(如UTF-8)和保存时的编码方案不一致时,则会出现中文显示乱码.解决方案: ...
- boost库的使用
我的经验:在强调运行效率的场合:shared_ptr/weak_ptr很好用,尤其是weak_ptr这个能够判断一个对象的生命周期的玩意,可以简化和扩展很多设计.unordered系列的容器也很不错. ...
- 【leetcode❤python】 189. Rotate Array
#-*- coding: UTF-8 -*-#由于题目要求不返回任何值,修改原始列表,#因此不能直接将新生成的结果赋值给nums,这样只是将变量指向新的列表,原列表并没有修改.#需要将新生成的结果赋予 ...
- Linux下不同服务器间数据传输--转载
因为工作原因,需要经常在不同的服务器见进行文件传输,特别是大文件的传输,因此对linux下不同服务器间数据传输命令和工具进行了研究和总结.主要是rcp,scp,rsync,ftp,sftp,lftp, ...