赞
踩
最近,事业群上层领导要求7天内完成ABS项目中保理系统的一期开发。需求评审会后,我发现各个功能模块都有大量的文件材料展示与上传,为了提高开发效率,我与组长商量,我先开发文件模块,为其他同事提供公共方法,减少重复工作。
使用的前端技术栈:Bootstrap、Bootstrap-table、layer.js、layui.js、jquery.media.js
我的想法是:文件的展示依托于表格形式,表格内展示文件的类型、名称、操作等信息,然后通过表格中或表头上的按钮完成上传、下载、预览等操作。其次,我又考虑的文件模块复用性与拓展性,我将文件类型信息存入数据字典中。这样做的好处有两点:一是、方便以后文件类型的拓展,即新增加一种文件,不需要改页面,只需要配置数据字典;二是、方便同事复用文件模块方法,即调用者,只需要传入类型后,就可以渲染相关数据。文件模块和数据字段模块图示如下:
图1 - 文件管理模块图片
图2 - 数据字典模块图片
列表基于Bootstrap-table完成的文件展示,我在这块还做了一个优化:可以根据开发者传入的文件类型展示相应的文件,如果没有,也会展示该类,但是没有文件名称和操作。具体演示和代码如下:
演示:
图3 - 文件列表演示图片
页面代码:
- <!DOCTYPE html>
- <html>
- <meta charset="utf-8">
- <head th:include="include :: header">
- </head>
- <body class="gray-bg">
- <div class="wrapper wrapper-content ">
- <div class="row">
- <div class="col-sm-12">
- <div class="ibox float-e-margins">
- <label class="col-sm-2 control-label">上传文件例子</label>
- <input type="hidden" id="fileIds" name="fileIds">
- <div class="ibox-content">
- <div class="columns pull-left">
- <button type="button" class="layui-btn" id="uploadFile">
- <i class="fa fa-cloud"></i>上传文件1
- </button>
- <button type="button" class="btn btn-primary"
- onclick="uploadFilePage('A','fileTable')">
- <i class="fa fa-primary" aria-hidden="true"></i>上传文件2
- </button>
- </div>
- <div class="columns pull-right">
- <button class="btn btn-success" onclick="downloadZip1('1','A','')">一键打包下载1</button>
- <button class="btn btn-success" onclick="downloadZip2()">一键打包下载2</button>
- </div>
- <table class="table table-bordered" id="fileTable"></table>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div th:include="include :: footer"></div>
- <script type="text/javascript" src="/js/appjs/common/file/file.js"></script>
- <link href="/css/layui.css" rel="stylesheet">
- <script src="/js/layui.js"></script>
- </body>
- </html>
JS代码:考虑到文件的复用性,初始化表格的JS入参有好几个
- $(function () {
- initFileTable('1','A','','fileTable','1');
- });
- /**
- * 初始化文件表格
- *
- * @param belongId 所属ID (必传)
- * @param type 文件总类型 (必传)
- * @param fileTag 文件分类型
- * @param tableId 表格id (必传)
- * @param delFlag 删除表示 (必传)
- */
- function initFileTable(belongId,type,fileTag,tableId,delFlag) {
- $("#"+tableId).bootstrapTable({
- striped: true, // 设置为true会有隔行变色效果
- cache: false,
- sortable: false,
- url: filePrefix+"/listByBelongIdAndTypeAndFileTag",
- method: "get",
- dataType: "json", // 服务器返回的数据类型
- queryParams: {"belongId": belongId,"type":type,"fileTag":fileTag},
- onLoadSuccess: function(data) {
- },
- columns: [
- {
- checkbox: true
- },
- {
- class: 'uid',
- title: '序号',
- align: 'center',
- formatter: function (value, row, index) {
- return index + 1;
- }
- },
- {
- field: "id",
- visible: false
- },
- {
- field: "uuid",
- visible: false
- },
- {
- title: '上传文件',
- align: 'center',
- formatter: function (value, row, index) {
- return uploadFileBtn(row,tableId);
- }
- },
- {
- field: "typeName",
- align: 'center',
- title: "文件总类型",
- visible: false
- },
- {
- field: "fileTagName",
- align: 'center',
- title: "文件类型"
- },
- {
- field: "fileName",
- align: 'center',
- title: "文件名"
- },
- {
- title: '操作',
- align: 'center',
- formatter: function (value, row, index) {
- var id = row.id;
- if(id==null){
- return '-';
- }
- var p = '<a class="btn btn-warning btn-xs' + '" title="预览" mce_href="#" onclick="previewFile(\''
- + row.url
- + '\')">预览</a> ';
- var e = '<a class="btn btn-success btn-xs' + '" title="下载" mce_href="#" onclick="downloadFile(\''
- + id
- + '\')">下载</a> ';
- var d = '<a class="btn btn-danger btn-xs' + '" title="删除" mce_href="#" onclick="deleteFile(\''+ id+'\',\''+tableId+ '\')">删除</a> ';
-
-
- if(delFlag=='1'){
- return p + e + d;
- }else {
- return p + e;
- }
- }
- }
- ]
- })
-
- }
Java代码:
- -----------------Controller------------------
- /**
- * 文件Demo
- *
- * @return
- */
- @GetMapping()
- private String File(){
- return "common/file/file";
- }
-
-
- /**
- * 查询文件列表
- *
- * @param belongId
- * @param type
- * @param fileTag
- * @return
- */
- @GetMapping("/listByBelongIdAndTypeAndFileTag")
- @ResponseBody
- public List<FileDTO> listByTypeAndFileTag(@RequestParam("belongId") Long belongId,
- @RequestParam("type") String type,
- @RequestParam("fileTag") String fileTag){
- List<FileDTO> busFileDOList=new ArrayList<>();
- try {
- busFileDOList =fileService.listByBelongIdAndTypeAndFileTag(belongId,type,fileTag);
- } catch (Exception e) {
- log.info("查询文件信息,异常信息:[{}]",e.getMessage());
- }
- return busFileDOList;
- }
- -----------------Service------------------
- @Override
- public List<FileDTO> listByBelongIdAndTypeAndFileTag(Long belongId, String type, String fileTag) {
- return fileDao.listByBelongIdAndTypeAndFileTag(belongId,type,fileTag);
- }
文件上传,我这里提供了三种方式,第一种方式:我们原来项目中常用方法,它是使用了layui.js插件,这插件的作者帮助我们封装了好多前端方法和前端样式,方便我们调用;第二种方式:是我新想出来的一种方式,点击上传按钮,进入一个上传页面,在页面中有一个下拉框可以选择上传文件类型,还有一个上传按钮用来上传文件,然后点击提交;第三种方式:是原型上要求的方式,这次开发时间比较紧张,我在开发的中就没有研究和使用,它是把按钮放在了列表中,不同列代表上传不同的文件类型,用户体验感比较好。而且,我这里还做一个优化,如果上传的文件在列表中不存在文件,就在原位置插入,反之,则在这个类型文件的最后一行后边插入(因为要实现这个,我引入一个唯一标识UUID)。具体演示和代码如下:
方式一:
点击上传按钮,上传文件就可以,缺点就是要在按钮的方法中固定上传的类型,单类型可以使用。
图4 - 文件上传方式一演示图片
<button type="button" class="layui-btn" id="uploadFile"><i class="fa fa-cloud"></i>上传文件1</button>
- $(function () {
- fileUpload('A','A01','fileTable');
- });
-
- /**
- * 上传
- *
- * @param type
- * @param fileTag
- * @param tableId
- */
- function fileUpload(type,fileTag,tableId) {
- layui.use('upload', function () {
- var upload = layui.upload;
- //执行实例
- var uploadInst = upload.render({
- elem: '#uploadFile', //绑定元素
- url: filePrefix+'/uploadFile1/'+type+'/'+fileTag, //上传接口
- size: 102400,
- accept: 'file',
- done: function (data) {
- if (data.code == 0) {
- var busFile = data.busFile;
- //插入一条数据
- insertFile(busFile,tableId);
- }
- layer.msg(data.msg);
- },
- error: function (data) {
- layer.msg(data.msg);
- }
- });
- });
- }
-
- /**
- * 插入文件
- *
- * @param row
- * @param tableId
- */
- function insertFile(row,tableId) {
- var table = $("#"+tableId);
- var rows = table.bootstrapTable('getData');
- var type = row.type;
- var fileTag = row.fileTag;
- var uuid=null;
- var insertIndex = rows.length-1;
- //寻找插入文件文件位置和可能需要删除的行
- $.each(rows, function (i, oldRow) {
- if(type==oldRow.type && fileTag==oldRow.fileTag){
- if(null == oldRow.id){
- uuid=oldRow.uuid;
- insertIndex=i;
- }else {
- insertIndex=i+1;
- }
- }
- });
- // 删除表格空的数据
- if(uuid!=null){
- var values = [uuid];
- table.bootstrapTable('remove', {
- field: 'uuid',
- values: values
- });
- }
- // 表格插入一条
- table.bootstrapTable('insertRow', {
- index: insertIndex,
- row: row
- });
- }
- -----------------Controller------------------
- /**
- * 上传文件1
- *
- * @param file
- * @param type
- * @param fileTag
- * @return
- */
- @PostMapping("/uploadFile1/{type}/{fileTag}")
- @ResponseBody
- public R uploadFile1(@RequestParam("file") MultipartFile file, @PathVariable("type") String type, @PathVariable("fileTag") String fileTag) {
- log.info("上传文件开始,type:[{}],fileTag:[{}]",type,fileTag);
- if (file == null || StringUtil.isBlank(file.getOriginalFilename())) {
- log.info("未选择文件");
- return R.error("请选择需要上传的文件");
- }
- Map<String, Object> map = new HashMap<>(2);
- try {
- FileDTO busFile = fileService.uploadFile(file, type, fileTag);
- map.put("busFile", busFile);
- log.info("上传文件结束,type:[{}],fileTag:[{}],id:[{}],fileName:[{}]",type,fileTag,busFile.getId(),busFile.getFileFull());
- } catch (IOException e) {
- log.info("上传文件IO流异常:异常信息:[{}]",e.getMessage());
- return R.error("上传文件IO流异常:异常信息:"+e.getMessage());
- }catch (Exception e){
- log.info("上传文件异常:异常信息:[{}]",e.getMessage());
- return R.error("上传文件异常:异常信息:"+e.getMessage());
- }
- return R.ok(map);
- }
- -----------------Service------------------
-
- @Override
- public FileDTO uploadFile(MultipartFile file, String type, String fileTag) throws IOException {
- FileDTO busFile = new FileDTO();
- Date now = new Date();
- String fileName = file.getOriginalFilename();
- String preName = fileName.substring(0, fileName.lastIndexOf("."));
- String extName = fileName.substring(fileName.lastIndexOf(".") + 1);
-
- // 上传文件到Fast
- // StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);
- // String groupPath = storePath.getFullPath();
- // String serverPath = fdfsConfig.getUrl();
- String serverPath = "https://img-blog.csdnimg.cn";
- String groupPath = "/20200404131040657.png";
-
- String fileUrl=null;
- // 处理fileUrl
- if (serverPath.endsWith("/")) {
- fileUrl = serverPath + groupPath;
- } else {
- fileUrl = serverPath + "/" + groupPath;
- }
- //封装数据
- busFile.setFileName(preName)
- .setFileExt(extName)
- .setFileFull(fileName)
- .setUrl(fileUrl)
- .setType(type)
- .setServerPath(serverPath)
- .setGroupPath(groupPath)
- .setFileTag(fileTag)
- .setCreateTime(now)
- .setUpdateTime(now)
- .setDelFlag(0);
- fileDao.save(busFile);
- //处理数据
- DictDO dict = dictDao.getByTypeAndValue(type, fileTag);
- busFile.setTypeName(dict.getDescription());
- busFile.setFileTagName(dict.getName());
- busFile.setUuid(UUID.randomUUID().toString());
- return busFile;
- }
方式二:
点击上传按钮,进入上传页面:选择类型、上传文件、点击提交。
图5-文件上传方式二演示图片
图6 - 文件上传方式二演示图片
- ---------------------------按钮----------------------
- <button type="button" class="btn btn-primary" onclick="uploadFilePage('A','fileTable')">
- <i class="fa fa-primary" aria-hidden="true"></i>上传文件2</button>
- ---------------------------上传页面----------------------
- <!DOCTYPE html>
- <html>
- <meta charset="utf-8">
- <head th:include="include :: header">
- </head>
- <body class="gray-bg">
- <div class="wrapper wrapper-content ">
- <div class="row">
- <div class="col-sm-12">
- <div class="ibox float-e-margins">
- <div class="ibox-content">
- <form class="form-horizontal m-t" id="signupForm" method="post" enctype="multipart/form-data">
-
- <input type="hidden" id="type" name="type" th:value="${type}"/>
- <input type="hidden" id="tableId" name="tableId" th:value="${tableId}"/>
- <div class="form-group">
- <label class="col-sm-2 control-label">文件类型:<i style="color: red;">*</i></label>
- <div class="col-sm-4">
- <select id="fileTag" name="fileTag" data-placeholder="请选择文件类型"
- class="col-sm-4 form-control chosen-select "
- tabindex="2" style="width: 100%"> <i style="color: red;">*</i>
- <option th:each="busDict:${busDictList}"
- th:value="${busDict.value}"
- th:text="${busDict.name}"></option>
- </select>
- </div>
- </div>
-
- <div class="form-group">
- <label class="col-sm-2 control-label">文件名称:</label>
- <div class="col-sm-3">
- <input id="fileupload" type="file" name="file" style="display:none;" />
- <input type='text' class="form-control" name='textfield' id='textfield' readonly="readonly"/>
- </div>
- <div class="col-sm-1">
- <input id="excelImport" type="button" value="上传" class="btn btn-success"/>
- </div>
- </div>
-
- <div class="form-group">
- <div class="col-sm-12 col-sm-offset-6">
- <button type="button" class="btn btn-primary" onclick="uploadFile()" >提交</button>
- </div>
- </div>
- </form>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div th:include="include :: footer"></div>
- <link href="/css/layui.css" rel="stylesheet">
- <script src="/js/layui.js"></script>
- <script type="text/javascript" src="/js/appjs/common/file/uploadFile.js"></script>
- </body>
- </html>
- ---------------------------按钮JS----------------------
- /**
- * 上传文件页面
- *
- * @param type
- * @param tableId
- */
- function uploadFilePage(type,tableId) {
- var index = layer.open({
- type: 2,
- title: '上传文件',
- maxmin: true,
- shadeClose: false, // 点击遮罩关闭层
- area: ['800px', '520px'],
- content: filePrefix+'/uploadFilePage/' + type+'/'+tableId
- });
- layer.full(index);
- }
- ---------------------------页面JS----------------------
- var filePrefix = "/common/file";
- $(function () {
- });
-
- $("#excelImport").click(function() {
- $('#fileupload').click();
- });
- $('#fileupload').change(function(){
- $('#textfield').val( document.getElementById("fileupload").files[0].name);
- })
-
- function uploadFile() {
- var fileBtnId='signupForm';
- var type=$('#type').val();
- var fileTag= $('#fileTag option:selected').val();
- var tableId=$('#tableId').val();
- $.ajax({
- type: "POST",
- dataType: "json",
- cache: false,
- processData: false,
- contentType: false,
- url: filePrefix+"/uploadFile1/"+type+"/"+fileTag,
- data: new FormData($('#'+fileBtnId)[0]),
- success: function (data) {
- if (data.code == 0) {
- parent.layer.msg("操作成功");
- parent.insertFile(data.busFile,tableId);
- var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引
- parent.layer.close(index);
- } else {
- parent.layer.alert(data.msg)
- }
- }
- });
- }
- -----------------Controller------------------
- /**
- * 上传文件页面
- *
- * @param type
- * @param model
- * @return
- */
- @GetMapping("/uploadFilePage/{type}/{tableId}")
- public String uploadFilePage(@PathVariable("type") String type,@PathVariable("tableId") String tableId, Model model) {
- List<DictDO> busDictList = dictDao.listByType(type);
- model.addAttribute("type",type);
- model.addAttribute("tableId",tableId);
- model.addAttribute("busDictList",busDictList);
- return "common/file/uploadFile";
- }
-
- /**
- * 上传文件2
- *
- * @param file
- * @param type
- * @param fileTag
- * @return
- */
- @PostMapping("/uploadFile2")
- @ResponseBody
- public R uploadFile2(@RequestParam("file") MultipartFile file,@RequestParam("type") String type, @RequestParam("fileTag") String fileTag) {
- log.info("上传文件开始,type:[{}],fileTag:[{}]",type,fileTag);
- if (file == null || StringUtil.isBlank(file.getOriginalFilename())) {
- log.info("未选择文件");
- return R.error("请选择需要上传的文件");
- }
- Map<String, Object> map = new HashMap<>(2);
- try {
- FileDTO busFile = fileService.uploadFile(file, type, fileTag);
- map.put("busFile", busFile);
- log.info("上传文件结束,type:[{}],fileTag:[{}],id:[{}],fileName:[{}]",type,fileTag,busFile.getId(),busFile.getFileFull());
- } catch (IOException e) {
- log.info("上传文件IO流异常:异常信息:[{}]",e.getMessage());
- return R.error("上传文件IO流异常:异常信息:"+e.getMessage());
- }catch (Exception e){
- log.info("上传文件异常:异常信息:[{}]",e.getMessage());
- return R.error("上传文件异常:异常信息:"+e.getMessage());
- }
- return R.ok(map);
- }
- -----------------Service------------------
- 与方式一相同
方式三:
点击上传按钮,就可以上传文件。
图7 - 文件上传方式三演示图片
没有页面代码,页面是通过js渲染的。
- /**
- * 上传文件按钮
- *
- * @param row
- * @param tableId
- * @returns {string}
- */
- function uploadFileBtn(row,tableId) {
- var formId=row.uuid;
- return '<button type="button" class="btn btn-primary" style="width: 82px;height: 25px;position: relative">'+
- '<form id="'+formId+'" method="post" enctype="multipart/form-data">' +
- '<input type="hidden" name="type" value="'+row.type+'"/>'+
- '<input type="hidden" name="fileTag" value="'+row.fileTag+'"/>'+
- '<input type="file" name="file" onchange="uploadFile(\''+formId+'\',\''+tableId+'\')" style="width: 100%;height: 25px;padding:0;position: absolute;font-size: 10px;left:0;top: 0;opacity: 0;z-index:2;filter:alpha(opacity=0);cursor: pointer;"/>'+
- '</form>'+
- '<span style="position: absolute;left: 10%;top: 3px;z-index: 1;" >上传文件3</span>'+
- '</button>';
- }
-
-
- /**
- * 上传文件按钮-上传方法
- *
- * @param formId
- * @param tableId
- */
- function uploadFile(formId,tableId) {
- $.ajax({
- type: "POST",
- dataType: "json",
- cache: false,
- processData: false,
- contentType: false,
- url: filePrefix+"/uploadFile2",
- data: new FormData($('#'+formId)[0]),
- success: function (data) {
- if (data.code == 0) {
- layer.msg("上传成功");
- insertFile(data.busFile,tableId);
- } else {
- layer.alert(data.msg)
- }
- }
- });
- }
- -----------------Controller------------------
- /**
- * 上传文件2
- *
- * @param file
- * @param type
- * @param fileTag
- * @return
- */
- @PostMapping("/uploadFile2")
- @ResponseBody
- public R uploadFile2(@RequestParam("file") MultipartFile file,@RequestParam("type") String type, @RequestParam("fileTag") String fileTag) {
- log.info("上传文件开始,type:[{}],fileTag:[{}]",type,fileTag);
- if (file == null || StringUtil.isBlank(file.getOriginalFilename())) {
- log.info("未选择文件");
- return R.error("请选择需要上传的文件");
- }
- Map<String, Object> map = new HashMap<>(2);
- try {
- FileDTO busFile = fileService.uploadFile(file, type, fileTag);
- map.put("busFile", busFile);
- log.info("上传文件结束,type:[{}],fileTag:[{}],id:[{}],fileName:[{}]",type,fileTag,busFile.getId(),busFile.getFileFull());
- } catch (IOException e) {
- log.info("上传文件IO流异常:异常信息:[{}]",e.getMessage());
- return R.error("上传文件IO流异常:异常信息:"+e.getMessage());
- }catch (Exception e){
- log.info("上传文件异常:异常信息:[{}]",e.getMessage());
- return R.error("上传文件异常:异常信息:"+e.getMessage());
- }
- return R.ok(map);
- }
- -----------------Service------------------
- 与方式一相同
通过预览按钮进入预览页面,现在支持预览文件格式只有图片和PDF。具体演示和代码如下:
演示:
图8 - 文件预览演示图片
页面代码:
- <!DOCTYPE html>
- <html>
- <meta charset="utf-8">
- <head th:include="include :: header">
- </head>
- <body class="gray-bg">
- <div class="wrapper wrapper-content ">
- <div class="row">
- <div class="col-sm-12">
- <div class="ibox float-e-margins">
- <div class="ibox-content" align="center">
- <a class="media" th:href="${url}"></a>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div th:include="include :: footer"></div>
- <script type="text/javascript" src="/js/media/jquery.media.js"></script>
- <script type="text/javascript">
- $(function() {
- $('a.media').media({width:1200, height:600});
- $('a.mediase').media({width:1200, height:600});
- });
- </script>
- </body>
- </html>
JS代码:
- /**
- * 预览文件
- *
- * @param url
- */
- function previewFile(url) {
- //获取最后一个.的位置
- var index= url.lastIndexOf(".");
- //获取后缀
- var ext = url.substr(index+1);
- if(ext=='docx'||ext=='doc'||ext=='txt'||
- ext=='zip'||ext=='xlsx'||ext=='xls'||
- ext=='ppt'||ext=='pptx'){
- layer.msg("不支持此"+ext+"格式文件预览");
- return;
- }
- var index = layer.open({
- type: 2,
- title: '预览文件',
- maxmin: true,
- shadeClose: false, // 点击遮罩关闭层
- area: ['800px', '520px'],
- content: filePrefix+'/previewFile?url=' + url
- });
- layer.full(index);
- }
Java代码:
- /**
- * 预览文件
- *
- * @param url
- * @param model
- * @return
- */
- @GetMapping("/previewFile")
- public String previewFile(@RequestParam("url") String url, Model model) {
- model.addAttribute("url",url);
- return "common/file/previewFile";
- }
点击下载按钮,就可下载。具体代码如下:
页面代码:
没有页面代码,JS渲染了一个按钮。
JS代码:
- /**
- * 下载文件
- *
- * @param id
- */
- function downloadFile(id) {
- window.location.href = filePrefix+"/downloadFile/" + id;
- }
Java代码:
- /**
- * 下载
- *
- * @param id
- * @return
- * @throws Exception
- */
- @GetMapping("/downloadFile/{id}")
- public ResponseEntity<byte[]> downloadFile(@PathVariable("id") Long id){
- FileDO file = fileDao.get(id);
- log.info("下载文件开始,文件id:[{}],文件名称:[{}]",file.getId(),file.getFileFull());
- byte[] content = ZipDownloadUtil.downloadUrlConvertByte(file.getUrl());
- HttpHeaders headers = new HttpHeaders();
- try {
- headers.set("Content-Disposition", "attachment;Filename=" + URLEncoder.encode(file.getFileFull(), "UTF-8"));
- } catch (UnsupportedEncodingException e) {
- log.info("文件名编码集转换异常,异常信息[{}]",e.getMessage());
- }
- HttpStatus statusCode = HttpStatus.OK;
- ResponseEntity<byte[]> entity = new ResponseEntity<>(content, headers, statusCode);
- return entity;
- }
点击删除按钮,弹出删除却框,点击确定后删除,我这里是逻辑删除,只更新数据删除标识,不删除数据库记录和文件服务器中的文件。具体演示和代码如下:
演示:
图9 - 文件删除演示图片
页面代码:
没有页面代码,JS渲染了一个按钮。
JS代码:
- /**
- * 删除文件
- *
- * @param id
- * @param tableId
- */
- function deleteFile(id,tableId) {
- layer.confirm("确认要删除此文件吗?",
- {btn: ['确定', '取消']}, function () {
- $.ajax({
- cache: true,
- type: "get",
- url: filePrefix+"/deleteFile/" + id,
- async: false,
- error: function (request) {
- parent.layer.alert("Connection error");
- },
- success: function (data) {
- if (data.code == 0) {
- var table = $("#"+tableId);
- var values = [parseInt(id)];
- table.bootstrapTable('remove', {
- field: 'id',
- values: values
- });
- layer.closeAll('dialog');
- parent.layer.msg("文件删除成功");
- } else {
- parent.layer.alert(data.msg)
- }
-
- }
- });
- })
- }
Java代码:
- /**
- * 删除文件
- *
- * @param id
- * @return
- */
- @ResponseBody
- @GetMapping("/deleteFile/{id}")
- public R deleteFile(@PathVariable("id") Long id) {
- try {
- fileDao.updateDelFlagById(id);
- } catch (Exception e) {
- log.info("删除文件信息,异常信息:[{}]",e.getMessage());
- return R.error("异常信息:"+e.getMessage());
- }
- return R.ok();
- }
我这里提供了两种打包下载方法方式,第一种方式:根据文件类型和所属ID打成一个压缩包,第二种方式:根据所属id的集合批量下载,并且压缩包中会按照所属ID和文件类型创建不同目录下载(这块搞了好久,我对Java IO流不是很熟悉;JDK8 Stream 分组的功能帮了我很大忙,JDK8 Stream的使用,见我写的这篇文章《JDK8都发行5年多了,你还不会使用Stream流和Lambda表达式吗?》)。
方式一:
点击一键打包下载按钮,就可以下文件,这种方式需要传入文件类型和所属ID,具体代码如下。
<button class="btn btn-success" onclick="downloadZip1('1','A','')">一键打包下载1</button>
- /**
- * 打包下载1
- *
- * @param belongId
- * @param type
- * @param fileTag
- */
- function downloadZip1(belongId,type,fileTag) {
- window.location.href = filePrefix+"/downloadZip1?belongId=" + belongId+"&type="+type+"&fileTag"+fileTag;
- }
- -----------------Controller------------------
- /**
- * 打包下载1
- *
- * @param belongId
- * @param type
- * @param fileTag
- */
- @GetMapping("/downloadZip1")
- @ResponseBody
- public void downloadZip1(@RequestParam("belongId") Long belongId,
- @RequestParam("type") String type,
- @RequestParam("fileTag") String fileTag,
- HttpServletResponse response) {
- log.info("打包下载文件开始,文件所属id:[{}],文件总类型:[{}],文件类型:[{}]",belongId,type,fileTag);
- try {
- fileService.downloadZip(belongId,type,fileTag,"压缩包",response);
- log.info("打包下载文件结束,文件所属id:[{}],文件总类型:[{}],文件类型:[{}]",belongId,type,fileTag);
- } catch (Exception e) {
- log.error("打包下载文件异常,异常信息:[{}]", e.getMessage());
- }
- }
- -----------------Service------------------
- @Override
- public void downloadZip(Long belongId, String type, String fileTag, String zipFilename, HttpServletResponse response) throws IOException {
-
- Map<String, Object> map = new HashMap<>(4);
- map.put("belongId", belongId);
- map.put("type", type);
- map.put("fileTag", fileTag);
- List<FileDTO> list = fileDao.list(map);
- List<byte[]> contentList = new ArrayList<>();
- List<String> filenameList = new ArrayList<>();
- String typeName = "";
- if (!list.isEmpty()) {
- typeName = list.get(0).getTypeName();
- list.forEach(x -> {
- log.info("文件名称和url,name:[{}],url:[{}] ", x.getFileName(), x.getUrl());
- if (StringUtil.isNotBlank(x.getUrl())) {
- contentList.add(ZipDownloadUtil.downloadUrlConvertByte(x.getUrl()));
- filenameList.add(getFilename(x));
- }
- });
- }
-
- ZipDownloadUtil.downloadZip(response, zipFilename, contentList, filenameList);
-
- }
-
方式二:
点击一键打包下载按钮,就可以下文件,这种方式需要所属ID类型和压缩包名称,具体代码如下。
<button class="btn btn-success" onclick="downloadZip2()">一键打包下载2</button>
- /**
- * 打包下载2
- */
- function downloadZip2() {
- var params={};
- params.belongIds=[1,2];
- params.zipFilename='测试';
- var param = jQuery.param(params);
- window.location.href = filePrefix+"/downloadZip2?" + param;
- }
- -----------------Controller------------------
- /**
- *
- * 打包下载2
- *
- * @param belongIds
- * @param zipFilename
- */
- @GetMapping("/downloadZip2")
- @ResponseBody
- public void downloadZip2(@RequestParam("belongIds[]") List<Long> belongIds,
- @RequestParam("zipFilename") String zipFilename,
- HttpServletResponse response) {
- log.info("打包下载文件开始,文件所属id集合:[{}]", JsonUtil.beanToJson(belongIds));
- try {
- fileService.batchDownloadZip(belongIds,zipFilename,response);
- log.info("打包下载文件结束,文件所属id集合:[{}],压缩文件名称:[{}]", JsonUtil.beanToJson(belongIds),zipFilename);
- } catch (Exception e) {
- log.error("打包下载文件异常,异常信息:[{}]", e.getMessage());
- }
-
- }
- -----------------Service------------------
- @Override
- public void batchDownloadZip(List<Long> belongIdList, String zipFilename, HttpServletResponse response) throws IOException {
- //数据为空
- if (belongIdList.isEmpty()) {
- return;
- }
- List<byte[]> contentList = new ArrayList<>();
- List<String> filenameList = new ArrayList<>();
- //遍历每一个资产包
- belongIdList.forEach(belongId->{
- Map<String,Object> param = new HashMap<>(2);
- param.put("belongId", belongIdList.get(0));
- List<FileDTO> list = fileDao.list(param);
- //按文件类型分组
- Map<String, List<FileDTO>> map = list.stream().collect(Collectors.groupingBy(FileDTO::getTypeName));
- String partlPackageNo = "";
- //遍历分组
- map.forEach((key, value)->{
- String typeName=key;
- value.forEach(x->{
- log.info("文件名称和url,name:[{}],url:[{}] ", x.getUrl(), x.getFileName());
- contentList.add(ZipDownloadUtil.downloadUrlConvertByte(x.getUrl()));
- filenameList.add(partlPackageNo+"/"+typeName+"/"+getFilename(x));
- });
- });
- });
- //封装压缩包名字
- zipFilename=zipFilename+"_"+ LocalDateTime.now().toString()+".zip";
- ZipDownloadUtil.downloadZip(response, zipFilename, contentList, filenameList);
-
- }
springboot_demo: springboot_demo 《 springboot-some-function模块》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。