java常见3种文件上传速度对比和文件上传方法详细代码
在java里面文件上传的方式很多,最简单的依然是FileInputStream、FileOutputStream了,在这里我列举3种常见的文件上传方法代码,并比较他们的上传速度(由于代码是在本地测试,所以忽略网速的影响)
还是老规矩,大神请绕一下,里屋说话。
首先呢,使用springMVC原生上传文件方法,需要一些简单的配置,不多说,上图。

1.采用spring提供的上传文件的方法
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
@RequestMapping("springUpload") public String springUpload(HttpServletRequest request) throws IllegalStateException, IOException { long startTime=System.currentTimeMillis(); //将当前上下文初始化给 CommonsMutipartResolver (多部分解析器) CommonsMultipartResolver multipartResolver=new CommonsMultipartResolver( request.getSession().getServletContext()); //检查form中是否有enctype="multipart/form-data" if(multipartResolver.isMultipart(request)) { //将request变成多部分request MultipartHttpServletRequest multiRequest=(MultipartHttpServletRequest)request; //获取multiRequest 中所有的文件名 Iterator iter=multiRequest.getFileNames(); while(iter.hasNext()) { //一次遍历所有文件 MultipartFile file=multiRequest.getFile(iter.next().toString()); if(file!=null) { String path="E:/springUpload"+file.getOriginalFilename(); //上传 file.transferTo(new File(path)); } } } long endTime=System.currentTimeMillis(); System.out.println("Spring方法的运行时间:"+String.valueOf(endTime-startTime)+"ms"); return "/success"; } |
在这里故意加一个计时,待会就用它简单的比较上传时间问题(本人暂时还没能力处理资源占用问题,所以这里也不做比较)
2.第二位选手,采用file.Transto 来保存上传的文件,这是目前我认为最好的上传方式,也是我最喜欢的上传方式,代码简单,速度快。请看下面代码。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/* * 采用file.Transto 来保存上传的文件 */ @RequestMapping("fileUpload2") public String fileUpload2(@RequestParam("file") CommonsMultipartFile file) throws IOException { long startTime=System.currentTimeMillis(); System.out.println("fileName:"+file.getOriginalFilename()); String path="E:/"+new Date().getTime()+file.getOriginalFilename(); File newFile=new File(path); //通过CommonsMultipartFile的方法直接写文件(注意这个时候) file.transferTo(newFile); long endTime=System.currentTimeMillis(); System.out.println("采用file.Transto的运行时间:"+String.valueOf(endTime-startTime)+"ms"); return "/success"; } |
3.第三种采用流的方式上传,这种方法在新手学习的时候经常用到,但是我并不喜欢,因为它又慢又难写,请看
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@RequestMapping("fileUpload") public String fileUpload(@RequestParam("file") CommonsMultipartFile file) throws IOException { //用来检测程序运行时间 long startTime=System.currentTimeMillis(); System.out.println("fileName:"+file.getOriginalFilename()); try { //获取输出流 OutputStream os=new FileOutputStream("E:/"+new Date().getTime()+file.getOriginalFilename()); //获取输入流 CommonsMultipartFile 中可以直接得到文件的流 InputStream is=file.getInputStream(); byte[] bts = new byte[1024]; //一个一个字节的读取并写入 while(is.read(bts)!=-1) { os.write(bts); } os.flush(); os.close(); is.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } long endTime=System.currentTimeMillis(); System.out.println("采用流上传的方式的运行时间:"+String.valueOf(endTime-startTime)+"ms"); return "/success"; } |
方法写好了,接下来,我们在本地做个简单的评测,
1.写个简单的文件上传页面

2.分别选择同一个文件,稍微大一点(我这里上传的zookeeper3.3.6的安装包,大小为11M),以区别处他们的耗时差异(最好不实用ie,很容易崩溃,亲测)

3.统计耗时,请看下图,结果一目了然。

在此补充说明一点,如果你认为采用流的方式上传慢是因为我这里内存开辟小了,可以尝试开大一点,但是依然不影响他的速度最慢的地位,如果内存开的过大,反倒影响速度。

以上内容仅供学习,如果有需要源码的,请联系我。
解决使用Spring Boot、Multipartfile上传文件路径错误问题
彻底跟路径错误say拜拜!
题图:from Google
1.问题描述
- 关键字: SpringMVC 4.2.4 、 Spring Boot 1.3.1 、Servlet 3.0 、文件上传
- 报错信息:
java.io.IOException: java.io.FileNotFoundException: /tmp/tomcat.273391201583741210.8080/work/Tomcat/localhost/ROOT/tmp/source/IMG_20160129_132623.jpg (No such file or directory) - 问题源码: transferTo方法报错
1
2
3
4
5
6
7
8
9// 前端传入mulFileSource
// 创建压缩前源文件
File fileSourcePath = new File("tmp/source/");
File fileSource = new File(fileSourcePath, mulFileSource.getOriginalFilename());
if (!fileSourcePath.exists()) {
fileSourcePath.mkdirs();
}
// 将接收得图片暂存到临时文件中
mulFileSource.transferTo(fileSource);
2.问题分析
- 首先,看源码中文件定义,相对路径,预期路径应该是
项目路径/tmp/source/,但是报错确是一个系统临时文件路径(tomcat的)。 - 其次,由于是transferTo方法报错,因此应该是该方法写入文件时报错,因此,我们跟入方法源码。
1 |
public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpServletRequest {
//中间代码省略
/**
|
1 |
package org.apache.catalina.core; |
- 源码一目了然,使用Servlet3.0的支持的上传文件功能时,如果我们没有使用绝对路径的话,transferTo方法会在相对路径前添加一个
location路径,即:file = new File(location, fileName);。当然,这也影响了SpringMVC的Multipartfile的使用。 - 由于我们创建的File在
项目路径/tmp/source/,而transferTo方法预期写入的文件路径为/tmp/tomcat.273391201583741210.8080/work/Tomcat/localhost/ROOT/tmp/source/,我们并没有创建该目录,因此会抛出异常。
3.问题解决方案
- 使用绝对路径
- 修改
location的值
这个location可以理解为临时文件目录,我们可以通过配置location的值,使其指向我们的项目路径,这样就解决了我们遇到的问题。
在Spring Boot下配置location,可以在main()方法所在文件中添加如下代码:1
2
3
4
5
6
7
8
9/**
* 文件上传临时路径
*/
@Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setLocation("/app/pttms/tmp");
return factory.createMultipartConfig();
}
表单,enctype 和 input 的type=file 即可,例子使用单文件上传
<form enctype="multipart/form-data" method="POST"
action="/file/fileUpload">
图片<input type="file" name="file" />
<input type="submit" value="上传" />
</form>
1
2
3
4
5
@Controller
@RequestMapping("/file")
public class UploadFileController {
@Value("${file.upload.path}")
private String path = "upload/";
@RequestMapping(value = "fileUpload", method = RequestMethod.POST)
@ResponseBody
public String fileUpload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return "false";
}
String fileName = file.getOriginalFilename();
File dest = new File(path + "/" + fileName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
file.transferTo(dest); // 保存文件
return "true";
} catch (Exception e) {
e.printStackTrace();
return "false";
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
运行在保存文件 file.transferTo(dest) 报错
问题
dest 是相对路径,指向 upload/doc20170816162034_001.jpg
file.transferTo 方法调用时,判断如果是相对路径,则使用temp目录,为父目录
因此,实际保存位置为 C:\Users\xxxx\AppData\Local\Temp\tomcat.372873030384525225.8080\work\Tomcat\localhost\ROOT\upload\doc20170816162034_001.jpg
一则,位置不对,二则没有父目录存在,因此产生上述错误。
解决办法
transferTo 传入参数 定义为绝对路径
@Controller
@RequestMapping("/file")
public class UploadFileController {
@Value("${file.upload.path}")
private String path = "upload/";
@RequestMapping(value = "fileUpload", method = RequestMethod.POST)
@ResponseBody
public String fileUpload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return "false";
}
String fileName = file.getOriginalFilename();
File dest = new File(new File(path).getAbsolutePath()+ "/" + fileName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
file.transferTo(dest); // 保存文件
return "true";
} catch (Exception e) {
e.printStackTrace();
return "false";
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
另外也可以 file.getBytes() 获得字节数组,OutputStream.write(byte[] bytes)自己写到输出流中。
参考
https://blog.csdn.net/dany_zj_cn/article/details/82019253
https://blog.csdn.net/daniel7443/article/details/51620308
java常见3种文件上传速度对比和文件上传方法详细代码的更多相关文章
- python接口自动化(三十二)--Python发送邮件(常见四种邮件内容)番外篇——上(详解)
简介 本篇文章与前边没有多大关联,就是对前边有关发邮件的总结和梳理.在写脚本时,放到后台运行,想知道执行情况,会通过邮件.SMS(短信).飞信.微信等方式通知管理员,用的最多的是邮件.在linux下, ...
- java 常见几种发送http请求案例
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java ...
- 在java 中一种简单方式的声明静态Map常量的方法
我现在需要在一个类里面放一个HashMap,往里面放一些数据,每次要从数据库中取数据的时候先查找HashMap,看是否已经存在,若存在就直接提取,若不存在就从数据库中抽取数据之后再放到HashMap中 ...
- java+上传大视频文件断点续传
上周遇到这样一个问题,客户上传高清视频(1G以上)的时候上传失败. 一开始以为是session过期或者文件大小受系统限制,导致的错误. 查看了系统的配置文件没有看到文件大小限制, web.xml中s ...
- java的五种数据类型解析
不知道大家对java的简单数据类型是否了解,下面针对Java的五种类型简单数据类型表示数字和字符,进行详细的讲解和分析. 一.简单数据类型初始化 在Java语言中,简单数据类型作为类的成员变量声明时自 ...
- [原创]Java常见笔试题知识点汇总
前天数梦工厂来学校招聘,笔试题比较有特点,全是Java题,基本就是Java的一些特点.凭记忆按照题目找到一些必备知识点 (1). try {}里有一个return语句,那么紧跟在这个try后的fina ...
- java上传文件常见几种方式
1.ServletFileUpload 表单提交中当提交数据类型是multipare/form-data类型的时候,如果我们用servlet去做处理的话,该http请求就会被servlet容器,包装成 ...
- java+上传后的文件展示
文件夹结构支持 大文件上传控件6支持向服务器上传整个文件夹,并且在服务端保存时与本地目录结构完全保持一致,同时在数据库中也保留文件夹的层级结构.开发人员可以借助于数据库中的层级信息方便的管理文件,管理 ...
- [原创]java WEB学习笔记72:Struts2 学习之路-- 文件的上传下载,及上传下载相关问题
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- [LeetCode] 236. Lowest Common Ancestor of a Binary Tree_ Medium tag: DFS, Divide and conquer
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
- phpcms网页替换验证码功能 及 搜索功能
在使用phpcms替换网页的时候,除了正常的替换栏目.内容页等,其他的什么验证码啦,提交表单了,搜索功能了,这些在替换的时候可能会对一些默认文件有一些小小 的改变 下面就是自己在失败中成功的过程,最后 ...
- oracle中实现某个用户truncate 其它用户下的表
oracle文档中对truncate权限的要求是需要某表在当前登录的用户下,或者当前登录的用户有drop any table的权限. 但是如果不满足第一个条件的情况下,要让某用户满足第二个条件就导致权 ...
- dygod.net
# -*- coding: utf-8 -*- import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.sp ...
- configparser配置文件处理
创建一个configparser格式的文档: import configparser config = configparser.ConfigParser()config["DEFAULT& ...
- 隐藏非选中的checkBox
//隐藏非选中的checkBox function onlyCheckBox(){ $("#dtlTable tr:gt(0)").each(function(i) { var c ...
- django开发(一)
django基础 1.django配置模块的各文件作用 一般来说标红的文件是需要我们具体配置和修改等的文件 2.django项目和功能编写的步骤 注:上面是功能模块,下面是配置模块.配置和功能解耦分离 ...
- Html Title 标签
Html Title 标签 Title 是 HTML Head 内部标签 <html> <head> <!-- Title标签:HTML的标头标题 --> < ...
- Python Gevent协程自动切换IO
Gevent Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程. Gr ...
- P1903 [国家集训队]数颜色 / 维护队列
思路 带修莫队的板子 带修莫队只需要多维护一个时间的指针即可,记录一下每个询问在第几次修改之后,再回退或者前进几个修改操作 排序的时候如果a.l和b.l在一个块里,就看r,如果a.r和b.r在一个块里 ...