导航菜单
首页 >  前端如何实现FormData多文件上传功能并且传入参数  > 多文件上传:从前台到后台代码实现

多文件上传:从前台到后台代码实现

一、业务场景

 项目中有个功能模块是商品管理,其中需要使用到图片上传,而且是多文件上传,这是比较常规的操作,就自己来写这个功能。

商品管理这个功能,除去图片操作之外,常规的增、删、改、查很快完成,然后在把图片相关操作添加进来。

二、需求分析

 自己以前开发的项目中,涉及文件上传的功能倒是不少,可是涉及多文件上传的功能还真没有接触过。可是这不影响自己来做

这个功能,正好可以借此机会学习学习如何实现多文件上传的功能。要点有两个,一个是前端代码怎么添加多个文件,一个是后台

如何来接收多个文件。搞清楚这两个问题之后,剩下的事情会简单得多。

三、解决方案

自己首先完成多文件上传的前端代码,核心代码是创建一个FormData对象,然后获取页面中选择的文件数组之后,

循环遍历添加多个文件,并且多个文件是添加到同一个字段上,代码如下

var formData = new FormData();//循环获取上传个文件for (var i = 0, len = $("#upload_file")[0].files.length; i < len; i++) {var dataTemp = $("#upload_file")[0].files[i];//console.log("dataTemp--->", dataTemp);var fileName = dataTemp.name;var fivarype = fileName.substring(fileName.lastIndexOf('.')).toLowerCase();if(fivarype !== '.jpg' && fivarype !== '.png'){return layer.msg('错误提示:只能上传jpg或者png格式的图片!');}var fileSize = dataTemp.size;var limitSize = 2 * 1024 * 1024;//console.log("fileSize--->", fileSize);if(fileSize > limitSize){return layer.msg('错误提示:文件大小不能超过2M!');}formData.append("files", dataTemp);}

这样写有一个好处,可以单独判断每一个选中的文件是否符合特定的格式,大小是否符合要求,在前端可以做一个

简单的过滤。将所有的文件对象都添加到files这个字段之上,多单文件上传的时候自己以为只能添加一次,可是做

好这个功能之后,发现它可以添加多次。有的网友是直接添加formData.append("files",$("#upload_file")[0]); 这样也没问题,

只是在选择文件的时候,不会做相关的校验。html代码如下,

上传文件时,自己使用的是ajax请求来发送数据,代码如下,

var loadStatus = layer.load(1);//提交数据$.ajax({url: contextPath + '/goods/upload',type: 'post',headers:{'loginToken': "Bearer " + localStorage.loginToken},data: formData,cache: false,//上传文件无需缓存contentType: false,//必须processData: false,//用于对data参数进行序列化处理 这里必须falsesuccess: function (result) {/** { code: -1 count: null data: null message: "未获取到上传文件信息" status: "失败" url: null } *///console.log("result--->", result);if (result.code === 0) {layer.msg("提示信息:图片上传成功!");var tempArr = result.data;for(var i = 0, len = tempArr.length; i < len; i++){filePathList[filePathList.length] = tempArr[i];}//console.log("图片上传-filePathList--->", filePathList);handlerShowPicture();}else {layer.msg("错误提示: 图片上传失败");}

$("#upload_file").parent().html('');layer.close(loadStatus);// setTimeout(function () {// //延迟1 s 在关闭弹出窗口// layer.closeAll();// }, 1000);},error: function () {layer.msg('错误提示:上传图片出现异常,请稍后重试!');layer.close(loadStatus);// setTimeout(function () {// //延迟1 s 在关闭弹出窗口// layer.closeAll();// }, 1000);$("#upload_file").parent().html('');},timeout: 180000,complete: function () {//$.messager.progress('close');}});

这种方式简单可用,在写过的很多项目中都是使用这种方式来上传文件。

 

后端代码经过反反复复的摸索之后,操作依赖也并不复杂,一个是接收文件数组的时候,直接在方法的形参中进行接收,代码如下

/** * @description: 商品图片上传 * @date: 2022/1/28 15:31 * @param : MultipartFile[] * @return: ResultVO *///@PostMapping("/upload")@RequestMapping(value="/upload",method= RequestMethod.POST,consumes="multipart/form-data")public ResultVO uploadFile(@RequestParam MultipartFile[] files){List filePathList = null;try{if(files == null){return ResultVOUtil.error(-1, "文件不存在");}

for(int i = 0, len = files.length; i < len; i++){MultipartFile file = files[i];

long fileSize = file.getSize();

if(fileSize > giftLimitSize || fileSize == 0){log.error("文件大小超出限制:" + fileSize);return ResultVOUtil.error(-1, "只能上传大小2M以内的图片");}

String fileName = file.getOriginalFilename();if(StringUtils.isBlank(fileName)){log.error("文件名称错误:" + fileName);return ResultVOUtil.error(-1, "文件名称错误");}

String fileSuffixName = fileName.substring(fileName.lastIndexOf(".") + 1);if(!typeSet.contains(fileSuffixName)){log.error("文件后缀名错误:" + fileSuffixName);return ResultVOUtil.error(-1, "文件后缀名错误");}}

filePathList = this.goodsManageService.uploadPicture(files);

}catch (Exception ex){log.error("图片上传操作异常--->" + ex.getMessage());ex.printStackTrace();}

log.info("图片上传返回数据为--->" + filePathList);if(Objects.equal(filePathList, null)){return ResultVOUtil.error(-1, "图片上传操作失败");}else{return ResultVOUtil.success("上传成功", filePathList);}}

在service中具体的处理逻辑如下,

@Overridepublic List uploadPicture(MultipartFile[] files) throws Exception {if(files == null){log.error("参数-files-错误{}:", files);return null;}

String targetPath = String.join(File.separator, linuxPath, "3");File tempPath = new File(targetPath);if(!tempPath.exists()){tempPath.mkdirs();}

String destFileName = "";List filePathList = new ArrayList();try{for(int i = 0, len = files.length; i < len; i++) {MultipartFile file = files[i];String fileName = file.getOriginalFilename();

String fileSuffixName = fileName.substring(fileName.lastIndexOf(".") + 1);

destFileName = CommonUtil.getUUID() + "." + fileSuffixName;String targetFile = String.join(File.separator, targetPath, destFileName);File destFile = new File(targetFile);if(!destFile.exists()){destFile.createNewFile();}file.transferTo(destFile);

String returnPath = File.separator + String.join(File.separator, "3", destFileName);boolean isWin = System.getProperty("os.name").toLowerCase().contains("win");if(isWin){//windows 系统 进行路径替换 将 / 替换为 \\returnPath = returnPath.replaceAll("\\\\", "/");}

filePathList.add(returnPath);}}catch (Exception ex){log.error("文件保存异常:" + ex.getMessage());return null;}

return filePathList;}

主要做的一个操作就是接收文件数组,然后将文件保存到自己指定的一个目录下面即可,核心代码是

file.transferTo(destFile);file表示文件数组中的对象,destFile表示目标文件的全路径,包含文件后缀名,这句代码的含义就是将上传的文件保存到指定的文件当中。最后按照自己业务的要求返回指定的文件路径,不是文件的全路径,因为在显示图片的时候传的参数是一个相对路径,后台处理的时候加上路径前缀即可。图片显示的方法如下,public void showPicture(String filePath, HttpServletResponse response) throws Exception {if(StringUtils.isBlank(filePath)){log.error("参数-filePath-错误");return;}String realPath = linuxPath + filePath;String result = "-1";File file = new File(realPath);response.setContentType("image/jpeg");

try (FileInputStream fis = new FileInputStream(realPath); OutputStream os = response.getOutputStream();){int len = 0;byte[] buffer = new byte[1024];while ((len = fis.read(buffer)) != -1){os.write(buffer, 0, len);}os.flush();} catch (Exception ex) {log.error("图片显示服务错误:" + ex.getMessage());}}

至此整个多文件上传的功能,全部搞定,功能完成,效果如下

 

 

 

 

参考博文:

前端代码

http://www.manongjc.com/detail/22-chxcnufnrzpbzfn.html

后台代码

https://www.cnblogs.com/ainyi/p/11345714.html

相关推荐: