vue upload组件
选中多个文件上传
通过axios请求
onUploadProgress
方法监听on-progress
on-su***ess
用这两个钩子函数实现进度条 下面有对应的函数。
本文是每个文件一个请求上传
也可以用一个请求上传多个文件,需要将文件遍历添加到form
表单中,后端用request.getParts();
获取集合,有需要的可以改造一下。
官网地址:https://element.eleme.***/#/zh-***/
<template>
<div>
<!-- multiple 允许上传多个文件 -->
<el-upload
:disabled="defaultDisabled"
ref="upload"
:multiple="multiFile"
action=""
:auto-upload="false"
:file-list = "fileList"
:http-request="uploadFile"
:on-change="changeFileLength"
:on-progress="uploadFileProcess"
:on-su***ess="handleFileSu***ess"
:on-preview = "handleFilePreview"
:on-remove = "handleFileRemove"
:before-upload = "beforeFileUpload"
:before-remove = "beforeFileRemove"
:limit="limit"
:on-exceed = "handleFileExceed">
<div v-if="!defaultDisabled">
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px;" size="small" type="su***ess" @click.stop="upload">上传到服务器</el-button>
</div>
<div slot="tip" class="el-upload__tip">文件大小不能超过1GB</div>
</el-upload>
</div>
</template>
<script>
module.exports = {
name: "upload",
props:{
data:{
type:Array,
default:[],
},
businessId:{
type:String,
default:"",
},
businessType:{
type:String,
default:"",
},
filePath:{
type:String,
required:true, //必须指定路径
default:"",
},
fileSize:{
type:Number,
default:(1024 * 1024 * 1024) // 默认1GB
},
fileNumber:{
type:Number,
default: 5 //默认5个文件
},
disabled:{
type:Boolean,
default:false,
},
multiple:{
type:Boolean,
default:true,
}
},
data(){
return {
fileList: this.data, // 文件列表
size:this.fileSize,// 文件大小限制
limit:this.fileNumber, // 文件数量
path:this.filePath, // 上传路径
defaultDisabled: this.disabled, // 是否禁用
formId: this.businessId, //业务主键
formTable: this.businessType, //业务表
multiFile:this.multiple //默认上传多个文件
}
},
created(){
this.getFileList();
},
methods:{
//文件上传前调用,如果返回false 和 失败状态 就会停止上传 并移除fileList的文件
beforeFileUpload(file) {
//校验文件大小
if (file.size >= this.size) {
//单位GB
let gb = (file.size / this.size).toFixed(4);
this.$notify.error({
title: '错误',
message: `${file.name} 文件大小超出${gb}GB,请重新选择!`
});
return false;
}
},
// 将文件名称进行编码 后台进行解码
changeFileLength(file, fileList){
let fileName = encodeURI(file.name) // 如果可以上传多个文件,这里需要用fileList.forEach()处理
let newFile = new File([file.raw],fileName);
newFile.uid = file.uid; // new File 没有uid属性,会导致组件底层报错,这里手动加上
file.raw = newFile; // 替换file的数据
},
// 用户点击上传调用
async upload(){
// 触发上传 调用配置 :http-request="uploadFile"
// 即触发 uploadFile函数
await this.$refs.upload.submit();
// 上传完成后执行的操作 ...
},
// 该函数调用多次
// 每次param参数传入一个文件
uploadFile(param){
// 创建FormData上传
let form = new FormData();
form.append('file', param.file)
form.enctype = "multipart/form-data";
// 将附加信息添加至FormData
form.append("filePath", this.path);
form.append("businessId", this.formId);
form.append("businessType", this.formTable);
//上传操作
this.uploadAttach(form,param).then(res => {
/*上传成功处理*/
param.onSu***ess(res);
}).catch(err => {
/*报错处理*/
this.$message.error(param.file.name + "上传错误");
param.onSu***ess(err);
for (let i = 0; i < this.fileList.length; i++) {
if (param.file.name === this.fileList[i].name) {
this.fileList.splice(i, 1);
break;
}
}
});
// }
},
// 上传文件
uploadAttach(data,fileObject){
return axios({
method:'post',
headers: {"Content-Type": "multipart/form-data"},
url:"/servlet/uploadServlet",//自定义上传url
data:data,
onUploadProgress: progressEvent => {
fileObject.progressFlag = true;
fileObject.su***essFlag = true;
let percent=(progressEvent.loaded / progressEvent.total * 100) | 0
fileObject.onProgress({percent});//调用uploader的进度回调
}
})
},
// 文件上传过程中的函数(在这里获取进度条的进度)
uploadFileProcess(event, file, fileList) {
this.fileList = fileList;
for (let i = 0; i < this.fileList.length; i++) {
if(file.name === this.fileList[i].name){
this.fileList[i].progressFlag = true;
this.fileList[i].su***essFlag = false;
if(event.percent != 100){
this.fileList[i].progressPercent = event.percent;
}
break;
}
}
},
// 文件上传成功的函数(用于文件上传成功之后的逻辑处理)
handleFileSu***ess(res,file,fileList){
this.fileList = fileList;
for (let i = 0; i < this.fileList.length; i++) {
if(file.name === this.fileList[i].name){
this.fileList[i].progressFlag = true;
if(file.status == 'su***ess' && res.data.code == 200){
this.fileList[i].su***essFlag = true;
res.data = res.data.data;
}else{
this.fileList[i].su***essFlag = false;
this.fileList.splice(i, 1);
}
break;
}
}
},
//查看文件
handleFilePreview(file){
console.log(file);
},
//删除文件
handleFileRemove(file,fileList){
console.log(file);
},
//文件数超出函数
handleFileExceed(files,fileList){
this.$notify.error({
title: '错误',
message: `只能选择${this.limit}个文件,请重新选择文件!`
});
},
//文件删除前的操作
beforeFileRemove(file, fileList){},
// 后台获取已经上传的文件列表
getFileList(){
if(this.businessId === "") return;
axios.get("/servlet/uploadServlet",{
businessId:this.businessId,
}).then(res => {
if(res.data.code === 200) this.fileList = res.data.data
}).catch(err=>{
this.$message.error("请求失败,请稍后再试!");
})
},
}
}
</script>
<style scoped>
</style>
java servlet请求
-
@MultipartConfig
使用这个注解后 用下面方式获取文件 -
Part part = request.getPart("file")
获取的是单文件 -
Collection<Part> parts = request.getParts();
获取的多文件
package ***.kaiyue.detection.upload;
import ***.App.Servlet.AppResponse;
import ***.alibaba.fastjson.JSONObject;
import ***.kaiyue.***mon.BeanFactory;
import ***.kaiyue.***mon.resource.AppConfig;
import ***.kaiyue.***mon.util.DateUtil;
import ***.kaiyue.jpf.attachment.service.FileService;
import ***.kaiyue.jpf.***mon.resource.***monResource;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.*;
import java.***.URLDecoder;
import java.util.Collection;
import java.util.HashMap;
import java.util.Random;
@WebServlet(name = "uploadServlet", urlPatterns = "/servlet/uploadServlet")
@MultipartConfig
public class uploadServlet extends HttpServlet {
@Override
public void destroy() {
super.destroy();
}
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
/**
* @param request
* @param response
*/
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
FileService fileService = (FileService) BeanFactory.getBeanByName("fileService");
AppResponse res = new AppResponse();
request.setCharacterEncoding("UTf-8");
String businessId = request.getParameter("businessId");//业务主键
String filePath = request.getParameter("filePath");//保存路径
String businessType = request.getParameter("businessType");//业务表名
HashMap<String, String> returnMap = new HashMap<>();
String fileId = "";//文件信息的主键
try {
//获取文件对象
Part part = request.getPart("file");
//获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
String header = part.getHeader("content-disposition");
String fileName = getFileName(header);
fileName = URLDecoder.decode(fileName, "UTF-8");
//获取配置的磁盘根目录
String path = AppConfig.getRootPath();
Random random = new Random();
int number = random.nextInt(1000);
//防止上传的文件重名 取一个新的名字
String newFileName = fileName.substring(0, fileName.lastIndexOf(".")) + DateUtil.getTimeStampId() + number +
fileName.substring(fileName.lastIndexOf("."));
File dir = new File(path + ***monResource.FILE_SEPARATOR + filePath + ***monResource.FILE_SEPARATOR);
if (!(dir.exists())) {
dir.mkdirs();
}
//写入磁盘
uploadFile(part, dir + ***monResource.FILE_SEPARATOR + newFileName);
String projectId = "";
String userId = "";
//保存到数据库
fileId = fileService.addFileRecord(fileName, filePath + ***monResource.FILE_SEPARATOR + newFileName, userId,
businessType, businessId, projectId, part.getSize());
returnMap.put("fileId", fileId);//主键
returnMap.put("businessId", businessId);
res.setData(returnMap);
res.setCode(AppResponse.OK);
res.setMessage("上传成功!");
} catch (Exception e) {
res.setData(returnMap);
res.setCode(AppResponse.PARAMETER_ERR);
res.setMessage("上传失败!");
e.printStackTrace();
}
PrintWriter out = response.getWriter();
out.println(JSONObject.toJSONString(res));
out.flush();
out.close();
}
/**
* 根据请求头解析出文件名
* 请求头的格式:火狐和google浏览器下:form-data; name="file"; filename="snmp4j--api.zip"
* IE浏览器下:form-data; name="file"; filename="E:\snmp4j--api.zip"
*
* @param header 请求头
* @return 文件名
*/
public String getFileName(String header) {
/**
* String[] tempArr1 = header.split(";");代码执行完之后,在不同的浏览器下,tempArr1数组里面的内容稍有区别
* 火狐或者google浏览器下:tempArr1={form-data,name="file",filename="snmp4j--api.zip"}
* IE浏览器下:tempArr1={form-data,name="file",filename="E:\snmp4j--api.zip"}
*/
header = header.substring(header.lastIndexOf("\\") + 1).replaceAll("\"", "");
String[] tempArr1 = header.split(";");
/**
*火狐或者google浏览器下:tempArr2={filename,"snmp4j--api.zip"}
*IE浏览器下:tempArr2={filename,"E:\snmp4j--api.zip"}
*/
String[] tempArr2 = tempArr1[2].split("=");
//获取文件名,兼容各种浏览器的写法
String fileName = tempArr2[1].substring(tempArr2[1].lastIndexOf("\\") + 1).replaceAll("\"", "");
return fileName;
}
private void uploadFile(Part part, String path)
throws Exception {
InputStream stream = null;
OutputStream out = null;
stream = part.getInputStream();
out = new FileOutputStream(path);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {
out.write(buffer, 0, bytesRead);
}
out.close();
stream.close();
}
}
效果
文件比较大