vue upload组件
选中多个文件上传
通过axios请求
onUploadProgress
方法监听
on-progress
on-success
用这两个钩子函数实现进度条 下面有对应的函数。
本文是每个文件一个请求上传
也可以用一个请求上传多个文件,需要将文件遍历添加到form
表单中,后端用request.getParts();
获取集合,有需要的可以改造一下。
官网地址:https://element.eleme.cn/#/zh-CN/
<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-success="handleFileSuccess":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="success" @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) {//单位GBlet 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";// 将附加信息添加至FormDataform.append("filePath", this.path);form.append("businessId", this.formId);form.append("businessType", this.formTable);//上传操作this.uploadAttach(form,param).then(res => {/*上传成功处理*/param.onSuccess(res);}).catch(err => {/*报错处理*/this.$message.error(param.file.name + "上传错误");param.onSuccess(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",//自定义上传urldata:data,onUploadProgress: progressEvent => {fileObject.progressFlag = true;fileObject.successFlag = true;let percent=(progressEvent.loaded / progressEvent.total * 100) | 0fileObject.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].successFlag = false;if(event.percent != 100){this.fileList[i].progressPercent = event.percent;}break;}}},// 文件上传成功的函数(用于文件上传成功之后的逻辑处理)handleFileSuccess(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 == 'success' && res.data.code == 200){this.fileList[i].successFlag = true;res.data = res.data.data;}else{this.fileList[i].successFlag = 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 parts = request.getParts();
获取的多文件
package com.kaiyue.detection.upload;import com.App.Servlet.AppResponse;import com.alibaba.fastjson.JSONObject;import com.kaiyue.common.BeanFactory;import com.kaiyue.common.resource.AppConfig;import com.kaiyue.common.util.DateUtil;import com.kaiyue.jpf.attachment.service.FileService;import com.kaiyue.jpf.common.resource.CommonResource;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.net.URLDecoder;import java.util.Collection;import java.util.HashMap;import java.util.Random;@WebServlet(name = "uploadServlet", urlPatterns = "/servlet/uploadServlet")@MultipartConfigpublic class uploadServlet extends HttpServlet {@Overridepublic void destroy() {super.destroy();}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}/** * @param request * @param response */@Overrideprotected 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 + CommonResource.FILE_SEPARATOR + filePath + CommonResource.FILE_SEPARATOR);if (!(dir.exists())) {dir.mkdirs();}//写入磁盘uploadFile(part, dir + CommonResource.FILE_SEPARATOR + newFileName);String projectId = "";String userId = "";//保存到数据库fileId = fileService.addFileRecord(fileName, filePath + CommonResource.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();}}
效果
文件比较大