若依项目上传下载附件实现
该上传下载附件的功能是基于bootstrap fileinput组件实现的。
其源码以及API地址如下:
bootstrap-fileinput源码:https://github.com/kartik-v/bootstrap-fileinput
bootstrap-fileinput在线API:http://plugins.krajee.com/file-input
bootstrap-fileinput Demo展示:http://plugins.krajee.com/file-basic-usage-demo
先看一下实现的效果图:此处与默认的上传样式有区别,是因为使用了【explorer】样式的主题。
下面记录一下具体实现步骤:
1、下载源码,将相应js、css分别放入static目录下,如下:主要是fileinput.min.js、fileinput.min.js、以及用于显示中文的zh.js、主题相关theme.min.js、theme.min.css
2、在include.html中引入相应js、css
<link th:href="@{/css/bootstrap-fileinput/fileinput.min.css}" rel="stylesheet"/> <link th:href="@{/css/bootstrap-fileinput/themes/explorer/theme.min.css}" rel="stylesheet"/>
<script th:src="@{/js/plugins/bootstrap-fileinput/fileinput.min.js}"></script> <script th:src="@{/js/plugins/bootstrap-fileinput/themes/explorer/theme.min.js}"></script> <script th:src="@{/js/plugins/bootstrap-fileinput/locales/zh.js}"></script>
3、先考虑后端的实现,此处需要在数据库中新建一张sys_attachment表,用于保存上传图片的相关信息,包括图片名称、图片路径等,生成语句如下:
DROP TABLE IF EXISTS `sys_attachment`; CREATE TABLE `sys_attachment` ( `id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT 'id', `business_type` varchar(40) DEFAULT NULL COMMENT '业务类型', `business_id` varchar(40) DEFAULT NULL COMMENT '业务Id', `file_path` varchar(100) DEFAULT NULL COMMENT '文件路径', `file_name_real` varchar(100) DEFAULT NULL COMMENT '真实的文件名', `file_name_show` varchar(100) DEFAULT NULL COMMENT '显示用的文件名', `file_size` bigint(10) DEFAULT NULL COMMENT '文件大小', `del_flag` int(10) DEFAULT NULL COMMENT '删除标记', `create_time` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=81 DEFAULT CHARSET=utf8 COMMENT='附件表';
4、后台创建sys_attachment对应的实体、mapper、service、controller文件。此处主要展示AttachmentController层代码:
@Controller @RequestMapping("/system/attachment") public class AttachmentController extends BaseController { private String prefix = "system/attachment"; @Autowired private IAttachmentService attachmentService; @RequiresPermissions("module:attachment:view") @GetMapping() public String attachment() { return prefix + "/attachment"; } @PostMapping("/load") @ResponseBody public String load(Attachment attachment) { List<Attachment> alist = attachmentService.selectAttachmentList(attachment); JSONObject jsonObject = new JSONObject(); jsonObject.put("success", true); jsonObject.put("alist", alist); return jsonObject.toString(); } @PostMapping("/delete") @ResponseBody public AjaxResult delete(String ids) { try { return toAjax(attachmentService.deleteAttachmentByIds(ids)); } catch (Exception e) { return error(e.getMessage()); } } @PostMapping("/save") @ResponseBody public AjaxResult save(Attachment attachment) { return toAjax(attachmentService.insertAttachment(attachment)); } }
5、将附件上传的方法,加入至 CommonController.java中
@RequestMapping("common/upload") @ResponseBody public String fileUpload(@RequestParam MultipartFile file) { JSONObject json = new JSONObject(); if(file!=null){ try { //上传文件,返回文件名 String fileName = FileUploadUtils.upload(Global.getDownloadPath(), file); //拼装文件名、文件路径信息,返回json json.put("success", true); json.put("filePath", Global.getDownloadPath() + fileName); json.put("fileNameReal", fileName); json.put("fileNameShow", file.getOriginalFilename()); json.put("fileSize", file.getSize()); return json.toString(); } catch (IOException e) { json.put("success", false); json.put("msg", "上传失败!"); return json.toString(); } }else { json.put("success", false); json.put("msg", "请选择附件!"); return json.toString(); } }
6、在ry-ui.js中封装【初始化上传附件】、【初始化编辑附件】、【执行上传附件】、【执行下载附件】的相关js代码。
其中相应的配置大部分都有注释解释了,如果需要更详细的了解具体的参数配置详情,可以参考:https://www.cnblogs.com/parker-yu/p/7207071.html,或查看官方API说明。
代码内容比较多,可能还有可以优化的地方,后续可能会优化。
//文件的操作 file :{ //初始化新增附件 initAddFiles : function (ctrlName,fileType){ var control = $('#' + ctrlName); // 具体参数自行查询 control.fileinput({ theme: "explorer", //主题 language: 'zh', //设置语言 uploadUrl: '/common/upload', //上传的地址 enctype: 'multipart/form-data', uploadAsync: true, showUpload: false, //是否显示上传按钮 showPreview: true,//是否展前预览 dropZoneEnabled: false,//是否显示拖拽区域 allowedFileExtensions : fileType == 'file' ? ['doc','docx','xls','xlsx','pdf','txt','ppt','zip'] : ['jpg','gif','png'],//接收的文件后缀 maxFileCount: 10, msgFilesTooMany: "选择上传的文件数量 超过允许的最大数值!", previewFileIcon: '<i class="fa fa-file"></i>', layoutTemplates :{ actionUpload:'',//去除上传预览缩略图中的上传图片; actionZoom:'', //去除上传预览缩略图中的查看详情预览的缩略图标。 }, allowedPreviewTypes: ['image'], previewFileIconSettings: { 'doc': '<i class="fa fa-file-word-o text-primary"></i>', 'xls': '<i class="fa fa-file-excel-o text-success"></i>', 'ppt': '<i class="fa fa-file-powerpoint-o text-danger"></i>', 'pdf': '<i class="fa fa-file-pdf-o text-danger"></i>', 'zip': '<i class="fa fa-file-archive-o text-muted"></i>', 'txt': '<i class="fa fa-file-text-o text-info"></i>', }, previewFileExtSettings: { // configure the logic for determining icon file extensions 'doc': function(ext) {return ext.match(/(doc|docx)$/i);}, 'xls': function(ext) {return ext.match(/(xls|xlsx)$/i);}, 'ppt': function(ext) {return ext.match(/(ppt|pptx)$/i);}, 'zip': function(ext) {return ext.match(/(zip|rar|tar|gzip|gz|7z)$/i);}, 'txt': function(ext) {return ext.match(/(txt|ini|csv|java|php|js|css)$/i);} } }); }, //初始化编辑附件 initEditFiles : function(ctrlName,fileType,businessType,businessId){ $.ajax({ type : "post", url : "/system/attachment/load", dataType : "json", data:{ "businessType" :businessType, "businessId" : businessId }, success : function(data) { //layer.msg('操作成功!'); $.file.loadEditFiles(ctrlName,fileType,data); }, error: function(XMLHttpRequest, textStatus, errorThrown) { layer.msg('操作失败!'); } }); }, //获取已上传需要编辑的附件 loadEditFiles: function (ctrlName,fileType,djson){ var control = $('#' + ctrlName); //后台返回json字符串转换为json对象 var reData = eval(djson).alist; // 预览图片json数据组 var preList = new Array(); for ( var i = 0; i < reData.length; i++) { var array_element = reData[i]; // 此处指针对.txt判断,其余自行添加 if(array_element.fileNameReal.indexOf("txt") > 0){ // 非图片类型的展示 preList[i]= "<div class='file-preview-other-frame'><div class='file-preview-other'><span class='file-icon-4x'><i class='fa fa-file-text-o text-info'></i></span></div></div>" }else if(array_element.fileNameReal.indexOf("doc") > 0){ preList[i]= "<div class='file-preview-other-frame'><div class='file-preview-other'><span class='file-icon-4x'><i class='fa fa-file-word-o text-primary'></i></span></div></div>" }else if(array_element.fileNameReal.indexOf("xls") > 0){ preList[i]= "<div class='file-preview-other-frame'><div class='file-preview-other'><span class='file-icon-4x'><i class='fa fa-file-excel-o text-success'></i></span></div></div>" }else if(array_element.fileNameReal.indexOf("ppt") > 0){ preList[i]= "<div class='file-preview-other-frame'><div class='file-preview-other'><span class='file-icon-4x'><i class='fa fa-file-powerpoint-o text-danger'></i></span></div></div>" }else if(array_element.fileNameReal.indexOf("zip") > 0){ preList[i]= "<div class='file-preview-other-frame'><div class='file-preview-other'><span class='file-icon-4x'><i class='fa fa-file-archive-o text-muted'></i></span></div></div>" }else if(array_element.fileNameReal.indexOf("pdf") > 0){ preList[i]= "<div class='file-preview-other-frame'><div class='file-preview-other'><span class='file-icon-4x'><i class='fa fa-file-pdf-o text-danger'></i></span></div></div>" }else{ // 图片类型 preList[i]= "<img src=\" "+ctx+"profile/download/"+array_element.fileNameReal+"\" class=\"file-preview-image\" height=\"80\" width=\"80\">"; } } var previewJson = preList; // 与上面 预览图片json数据组 对应的config数据 var preConfigList = new Array(); for ( var i = 0; i < reData.length; i++) { var array_element = reData[i]; var tjson = { caption: array_element.fileNameShow, // 展示的文件名 size : array_element.fileSize, width: '120px', url: '/system/attachment/delete', // 删除url key: array_element.fileNameReal, // 删除是Ajax向后台传递的参数 extra: {ids: array_element.id} }; preConfigList[i] = tjson; } // 具体参数自行查询 control.fileinput({ theme: "explorer", language: 'zh', //设置语言 uploadUrl: '/common/upload', //上传的地址 enctype: 'multipart/form-data', uploadAsync: true, showUpload: false, //是否显示上传按钮 showPreview: true,//是否展前预览 dropZoneEnabled: false,//是否显示拖拽区域 showRemove:false, //是否显示移除按钮 allowedFileExtensions : fileType == 'file' ? ['doc','docx','xls','xlsx','pdf','txt','ppt','zip'] : ['jpg','gif','png'],//接收的文件后缀 maxFileCount: 10, msgFilesTooMany: "选择上传的文件数量 超过允许的最大数值!", previewFileIcon: '<i class="fa fa-file"></i>', layoutTemplates :{ actionUpload:'',//去除上传预览缩略图中的上传图片; actionZoom:'', //去除上传预览缩略图中的查看详情预览的缩略图标。 }, allowedPreviewTypes: ['image'], initialPreview: previewJson, initialPreviewConfig: preConfigList, otherActionButtons:'<button type="button" class="kv-file-down btn btn-sm btn-default" data-key = {key} onclick="$.file.download(this)" title="下载附件"><i class="fa fa-cloud-download"></i></button>', previewFileIconSettings: { 'doc': '<i class="fa fa-file-word-o text-primary"></i>', 'xls': '<i class="fa fa-file-excel-o text-success"></i>', 'ppt': '<i class="fa fa-file-powerpoint-o text-danger"></i>', 'pdf': '<i class="fa fa-file-pdf-o text-danger"></i>', 'zip': '<i class="fa fa-file-archive-o text-muted"></i>', 'htm': '<i class="fa fa-file-code-o text-info"></i>', 'txt': '<i class="fa fa-file-text-o text-info"></i>', 'mov': '<i class="fa fa-file-video-o text-warning"></i>', 'mp3': '<i class="fa fa-file-audio-o text-warning"></i>', 'jpg': '<i class="fa fa-file-photo-o text-danger"></i>', 'gif': '<i class="fa fa-file-photo-o text-muted"></i>', 'png': '<i class="fa fa-file-photo-o text-primary"></i>' }, previewFileExtSettings: { // configure the logic for determining icon file extensions 'doc': function(ext) {return ext.match(/(doc|docx)$/i);}, 'xls': function(ext) {return ext.match(/(xls|xlsx)$/i);}, 'ppt': function(ext) {return ext.match(/(ppt|pptx)$/i);}, 'zip': function(ext) {return ext.match(/(zip|rar|tar|gzip|gz|7z)$/i);}, 'htm': function(ext) {return ext.match(/(htm|html)$/i);}, 'txt': function(ext) {return ext.match(/(txt|ini|csv|java|php|js|css)$/i);}, 'mov': function(ext) {return ext.match(/(avi|mpg|mkv|mov|mp4|3gp|webm|wmv)$/i);}, 'mp3': function(ext) {return ext.match(/(mp3|wav)$/i);} } }); }, //执行上传附件 uploadFile : function(ctrlName,businessType,businessId){ var control = $('#' + ctrlName); var file = control.val(); if(file != '' ){ //执行上传 control.fileinput("upload"); //上传成功后的处理 control.on("fileuploaded", function(event, outData) { var result = outData.response; var filePath = result.filePath; var fileNameReal = result.fileNameReal; var fileNameShow = result.fileNameShow; var fileSize = result.fileSize; $.ajax({ cache : true, type : "POST", url : "/system/attachment/save", data : { "businessType" : businessType, "businessId" : businessId, "filePath" : filePath, "fileNameReal" : fileNameReal, "fileNameShow" : fileNameShow, "fileSize" : fileSize, "delFlag" : '0' }, async : false, error : function(request) { }, success : function(data) { } }); }) } }, //执行下载附件 download : function(obj){ var $btn = $(obj),dataKey = $btn.data('key'); if(dataKey == false){ layer.msg('暂未上传,无法下载!'); }else{ window.location.href="/common/download?fileName="+dataKey; } }
}
7、页面调用。
在新增页面上:
<div class="form-group"> <label class="col-sm-3 control-label">附件上传:</label> <div class="col-sm-8"> <input id="file-Portrait" type="file" multiple="multiple" name="file"> </div> </div>
$(function() { //初始化上传组件 $.file.initAddFiles("file-Portrait","file");
});
使用ajax保存相应业务数据成功后,调用上传组件:
注意此处可以从data中获取businessId,需要覆写一下toAjax方法,需要将业务保存后的Id传入该json中,以便获取。
$.ajax({ cache : true, type : "POST", url : prefix + "/add", data : $('#form-notice-add').serialize(), async : false, error : function(request) { $.modal.alertError("系统错误"); }, success : function(data) { var businessId = data.businessId; $.file.uploadFile("file-Portrait","notice",businessId); $.operate.saveSuccess(data); } });
对于编辑页面上:
$(function() {
var businessId = $("#noticeId").val(); $.file.initEditFiles("file-Portrait","file","notice",businessId); });
自此上传与下载的功能基本实现了!