Java 单文件、多文件上传 / 实现上传进度条
博客地址:https://ainyi.com/76
日常,工作
在这里总结一下上传吧(是以前做过的练习,就汇总到个人博客吧)
java ssm 框架实现文件上传
实现:单文件上传、多文件上传(单选和多选),并且用 ajax 异步刷新,在当前界面显示上传的文件
后端
首先 springmvc 的配置文件要配置上传文件解析器:
<!-- 配置文件解析器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:defaultEncoding="utf-8">
<property name="uploadTempDir" value="/temp"></property>
<property name="maxUploadSize">
<value>209715200</value><!-- 200MB -->
</property>
<property name="maxInMemorySize">
<value>4096</value><!-- 4KB大小读写 -->
</property>
</bean>
其次在 pom.xml 中要配置上传文件的依赖
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
单文件上传
/**
* 单文件上传
* @param file
* @param request
* @return
* @throws IllegalStateException
* @throws IOException
* @throws JSONException
*/
public static String simUpload(MultipartFile file, HttpServletRequest request)
throws IllegalStateException, IOException, JSONException{
if(!file.isEmpty()){
String path = request.getSession().getServletContext().getRealPath("/upload");
//定义文件
File parent = new File(path);
if(!parent.exists()) parent.mkdirs();
HashMap<String, Object> map = new HashMap<String,Object>();
String oldName = file.getOriginalFilename();
long size = file.getSize();
//使用TmFileUtil文件上传工具获取文件的各种信息
//优化文件大小
String sizeString = TmFileUtil.countFileSize(size);
//获取文件后缀名
String ext = TmFileUtil.getExtNoPoint(oldName);
//随机重命名,10位时间字符串
String newFileName = TmFileUtil.generateFileName(oldName, 10, "yyyyMMddHHmmss");
String url = "upload/"+newFileName;
//文件传输,parent文件
file.transferTo(new File(parent, newFileName));
map.put("oldname",oldName);//文件原名称
map.put("ext",ext);
map.put("size",sizeString);
map.put("name",newFileName);//文件新名称
map.put("url",url);
//以json方式输出到页面
return JSONUtil.serialize(map);
}else{
return null;
}
}
多文件上传(整合了单选文件和多选文件的两种)
/**
* 多文件上传
* @param files
* @param request
* @return
* @throws IllegalStateException
* @throws IOException
* @throws JSONException
*/
public static List<HashMap<String, Object>> mutlUpload(MultipartFile[] files, HttpServletRequest request)
throws IllegalStateException, IOException, JSONException{
if(files.length > 0){
String path = request.getSession().getServletContext().getRealPath("/upload");
//定义文件
File parent = new File(path);
if(!parent.exists()) parent.mkdirs();
//创建这个集合保存所有文件的信息
List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
//循环多次上传多个文件
for (MultipartFile file : files) {
//创建map对象保存每一个文件的信息
HashMap<String, Object> map = new HashMap<String,Object>();
String oldName = file.getOriginalFilename();
long size = file.getSize();
//使用TmFileUtil文件上传工具获取文件的各种信息
//优化文件大小
String sizeString = TmFileUtil.countFileSize(size);
//获取文件后缀名
String ext = TmFileUtil.getExtNoPoint(oldName);
//随机重命名,10位时间字符串
String newFileName = TmFileUtil.generateFileName(oldName, 10, "yyyyMMddHHmmss");
String url = "upload/"+newFileName;
//文件传输,parent文件
file.transferTo(new File(parent, newFileName));
map.put("oldname",oldName);//文件原名称
map.put("ext",ext);
map.put("size",sizeString);
map.put("name",newFileName);//文件新名称
map.put("url",url);
listMap.add(map);
}
//以json方式输出到页面
return listMap;
}else{
return null;
}
}
前端
前端代码:
文件多选,实际上在
<input type="file"
name="fileupmulti"
accept="image/jpeg,image/png"
onchange="mutiFiles(this)"
multiple/>
多加了一个 multiple 属性
onchange 事件代码
// 单文件上传
function uploadFile(obj){
// 创建一个 FormData 对象,用一些键值对来模拟一系列表单控件
// 即把 form 中所有表单元素的 name 与 value 组装成一个 queryString
let form = new FormData();
let fileObj = obj.files[0];
form.append('doc',fileObj);
// ajax 代码...
}
// 多文件上传(多选)
function mutiFiles(obj){
let form = new FormData();
let fileObj = obj.files;
let length = fileObj.length;
// 将 fileObj 转换成数组
// let filese = Array.from(fileObj);
for(let i = 0; i < length; i++){
form.append('doc', fileObj[i]);
}
// ajax 代码...
}
// 多文件上传(单选:一个一个选择文件,最后点击提交按钮触发的方法)
function multipartone(){
let file1 = $('.fileupon11').get(0).files[0];
let file2 = $('.fileupon12').get(0).files[0];
let file3 = $('.fileupon13').get(0).files[0];
//如果都是空,则直接退出
isEmpty(file1) && isEmpty(file2) && isEmpty(file3) return;
let form = new FormData();
//用同一个名字,注入到controller层的参数数组
form.append('doc', file1);
form.append('doc', file2);
form.append('doc', file3);
// ajax 代码...
}
要想在当前界面显示上传的文件,而不跳转,就利用 ajax 异步请求
不过需要注意的是,我这里使用 FormData() 储存文件对象, ajax 要配上这几个参数才可实现文件上传:
$.ajax({
type: "post",
data: form, // FormData()对象
url: basePath+"/upload/mutl",
contentType: false, // 必须false才会自动加上正确的Content-Type
processData: false, // 必须false才会避开 jQuery 对 formdata 的默认处理, XMLHttpRequest会对 formdata 进行正确的处理
success: function(data){
// TODO
}
})
controller 层调用
package com.krry.controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.json.JSONException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.krry.util.UploadUtil;
/**
* 文件上传类
* KrryUploadController
* @author krry
* @version 1.0.0
*
*/
@Controller
@RequestMapping("/upload")
public class KrryUploadController {
/**
* 单文件上传
* @param file
* @param request
* @return
* @throws IllegalStateException
* @throws IOException
* @throws JSONException
*/
@ResponseBody
@RequestMapping(value = "/file")
public String krryupload(@RequestParam("doc") MultipartFile file, HttpServletRequest request) throws IllegalStateException, IOException, JSONException{
//调用工具类完成上传,返回相关数据到页面
return UploadUtil.simUpload(file, request);
}
/**
* 多文件上传
* @param file
* @param request
* @return
* @throws IllegalStateException
* @throws IOException
* @throws JSONException
*/
// 这里的MultipartFile[] file表示前端页面上传过来的多个文件,file对应页面中多个file类型的input标签的name,但框架只会将一个文件封装进一个MultipartFile对象,
// 并不会将多个文件封装进一个MultipartFile[]数组,直接使用会报[Lorg.springframework.web.multipart.MultipartFile;.<init>()错误,
// 所以需要用@RequestParam校正参数(参数名与MultipartFile对象名一致),当然也可以这么写:@RequestParam("file") MultipartFile[] files。
@ResponseBody
@RequestMapping(value = "/mutl")
public List<HashMap<String, Object>> krryuploadMutl(@RequestParam("doc") MultipartFile[] file, HttpServletRequest request) throws IllegalStateException, IOException, JSONException{
//调用工具类完成上传,返回相关数据到页面
return UploadUtil.mutlUpload(file, request);
}
}
进度条
要显示上传进度条,我这里采用原生 ajax 方法
function uploadFile(obj) {
// ...
// 一些获取上传对象的相关代码
// 创建一个 ajax 对象
var xhr = new XMLHttpRequest();
// 规定请求的类型、URL 以及是否异步处理请求。true为异步
// 请求是异步的。因为要实时获取到上传的进度,则请求需是异步的,如果是同步的话,会直到请求完成才能获取到响应
xhr.open("post", basePath+"/upload/file", true);
// 上传成功进入的回调函数
xhr.onreadystatechange = function(){
if(xhr.readyState==4 && xhr.status==200){ // 状态 4 和 200 代表和服务器端交互成功
// 获取上传成功的返回数据
var data = xhr.responseText.trim();
jdata = eval("("+data+")");
krry_uploadsuccess(jdata);
}
};
// 监听文件上传的进度
xhr.upload.addEventListener("progress", progressFunction, false);
// 发送http请求:将请求发送到服务器,与后台交互
xhr.send(form);
}
// 上传进度的回调函数
function progressFunction(event) {
let prograssbarDom = document.getElementById("prograssbar");
let fileRea = document.getElementById("fileRea");
if (prograssbarDom && event.lengthComputable) {
let percent = event.loaded / event.total; //文件上传进度百分比
let p = Math.floor(percent*100);
prograssbarDom.style.width = p+"%";
fileRea.innerHTML = p+"%";
}
}
附上优化文件大小的代码:
/**
* 将文件的字节数转换成文件的大小
* com.krry.uitl
* 方法名:format
* @author krry
* @param size
* @return String
* @exception
* @since 1.0.0
*/
public static String format(long size){
float fsize = size;
String fileSizeString;
if (fsize < 1024) {
fileSizeString = String.format("%.2f", fsize) + "B"; //2f表示保留两位小数
} else if (fsize < 1048576) {
fileSizeString = String.format("%.2f", fsize/1024) + "KB";
} else if (fsize < 1073741824) {
fileSizeString = String.format("%.2f", fsize/1024/1024) + "MB";
} else if (fsize < 1024 * 1024 * 1024) {
fileSizeString = String.format("%.2f", fsize/1024/1024/1024) + "GB";
} else {
fileSizeString = "0B";
}
return fileSizeString;
}
博客地址:https://ainyi.com/76
Java 单文件、多文件上传 / 实现上传进度条的更多相关文章
- js实现图片上传预览及进度条
原文js实现图片上传预览及进度条 最近在做图片上传的时候,由于产品设计的比较fashion,上网找了比较久还没有现成的,因此自己做了一个,实现的功能如下: 1:去除浏览器<input type= ...
- Progress.js – 为页面上的任意对象创建进度条效果
Progress.js 是一个 JavaScript 和 CSS3 的库,它帮助开发人员为网页上的每个对象创建和管理进度条效果.你可以设计自己的模板,进度条或者干脆定制. 您可以使用 Progress ...
- ajax实现无刷新上传附件并且显示进度条的实例
首先:得把php.ini中的post_max_size和upload_max_filesize改成200M或更大(进度条好看效果,默认是2M) html和js代码: <!DOCTYPE html ...
- android一个上传图片的样例,包含怎样终止上传过程,假设在上传的时候更新进度条(一)
先上效果图: Layout为: <? xml version="1.0" encoding="utf-8"?> <LinearLayout x ...
- 项目一、ajax上传数据(显示进度条)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- layui 魔改:上传时的真实进度条
这个问题本身不复杂,难点在于需要改 layui 的源码. HTML略. 网页的JS域: layui.use(['upload','element','layer'], function(){ var ...
- asp.net 文件上传 Uploadify HTML5 带进度条
参考的https://www.cnblogs.com/lvdabao/p/3452858.html这位,在此基础上略有修改: 1.根据Layer,将上传附件做成弹窗显示,引入frame弹窗,在项目当中 ...
- Ajax文件上传并添加Bootstrap进度条
1.项目中需要用到文件上传和显示进度,网上各种插件搞得头晕,决定自己实现一个 三个步骤:Ajax上传文件,获取上传进度,显示进度 html: <!DOCTYPE HTML> <htm ...
- ajax +formdata ,后台为PHP 实现上传整个文件夹(只适合谷歌浏览器)带进度条
PHP用超级全局变量数组$_FILES来记录文件上传相关信息的. 1.file_uploads=on/off 是否允许通过http方式上传文件 2.max_execution_time=30 允许脚本 ...
- 微信小程序-上传多张图片加进度条(支持预览、删除)
2018-12-24 详情示例见:https://www.cnblogs.com/cisum/p/9564898.html 2018-12-29 组件下载见:https://www.cnblogs.c ...
随机推荐
- [转]import xxx from 和 import {xxx} from的区别
原文地址:https://www.cnblogs.com/Abner5/p/7256043.html 1.vue import FunName from ‘../xxx’ 1.js export de ...
- php-7.3.4 configure: error: Please reinstall the libzip distribution
php-7.3.4 configure: error: Please reinstall the libzip distribution # wget https://libzip.org/downl ...
- groupby 的妙用(注意size和count)
Pandas的groupby()功能很强大,用好了可以方便的解决很多问题,在数据处理以及日常工作中经常能施展拳脚. 今天,我们一起来领略下groupby()的魅力吧. 首先,引入相关package: ...
- 【小实现】css after+border实现标签半菱形
<!DOCTYPE html> <html lang="en"> <head> <style> .span-line-begin { ...
- intellij查找接口的实现类
拿MyBatis的SqlSession为例 第一步:先找到这个接口 第二步:右击选择 再选择 第三步: 会得到如下 右击Closeable,因为SqlSession实现了它,选择Show Inplem ...
- ThinkPHP5远程代码执行高危漏洞(附:升级修复解决方法)
漏洞描述 由于ThinkPHP5框架对控制器名没有进行足够的安全检测,导致在没有开启强制路由的情况下,黑客构造特定的请求,可直接GetWebShell. 漏洞评级 严重 影响版本 ThinkPHP 5 ...
- ThinkPHP 中入口文件中的APP_DEBUG为TRUE时不报错,改为FALSE时报错
今天好不容易将一个新闻网做好了(ThinkPHP框架做的),但是,当我将入口文件中定义调试模式设为FALSE,即define('APP_DEBUG',False),然后再刷新网站的时候,就提示报错,报 ...
- 导出excel按照指定格式
1.项目有个需求,要按照特定格式 导出Excel表格. 正常的都是一行 ,下面是数据.这次有个变动,就是每隔 几列要换行,下面是数据.在下面是数据部分.花了一上午写了下需求,不难但是花时间 //实现特 ...
- 【Spring Boot学习之一】Spring Boot简介
环境 Java1.8 Spring Boot 1.3.2 一.Spring Boot特点1.使用java运行项目,内置tomcat,无需外部容器:2.减少XML配置,使用properties文件和注解 ...
- 头部文件jq嵌入笔记
var headHtml = '<div class="container">' + '<div class="navbar-header"& ...