Bootstrap框架---krajee插件fileinput--最好用的文件上传组件---
我们在前一章已经实现了?Bootstrap框架---Uploadify插件----多张图片上传交互方式二 。 ?Bootstrap框架---Uploadify插件----多张图片上传交互方式二 本章主要关注单多张图片上传在Bootstrap框架中的布局和实现。 我们在之前的文章中已经在SpringMVC基础框架的基础上应用了BootStrap的后台框架,在此基础上记录?单多张图片上传在Bootstrap框架中的布局方式三和实现。 基础项目源码下载地址为: SpringMVC+Shiro+MongoDB+BootStrap基础框架 我们在基础项目中已经做好了首页index的访问。 效果图Krajee的FileInput插件介绍介绍插件主页地址是: http://plugins.krajee.com/file-input 可以从这里看到很多Demo的代码展示: http://plugins.krajee.com/file-basic-usage-demo 这是一个增强的 HTML5 文件输入控件,是一个 Bootstrap 3.x 的扩展,实现文件上传预览,多文件上传等功能: bootstrap-fileinput是一款基于Bootstrap 3.x的html5文件上传插件。该文件上传插件带有预览图效果,可同时选择多个文件。该插件使用bootstrap CSS3样式来制作文件上传界面,美观大方。并且它提供了多国语言,你可以选择使用中文。 该文件上传插件比普通的文件上传插件功能更强大,它可以对图片、文本文件、HTML文件、视频文件、音频文件、flash文件生成预览图。另外,它还可以基于AJAX上传文件,拖拽上传文件,查看上传进度,可以选择性的预览,添加或删除文件。 特点该文件上传插件的特点有: AJAX上传功能基于HTML5 FormData(绝大多数现代浏览器都支持该属性)。在不支持该属性的浏览器中会回退为普通的文件上传组件。使用AJAX必须设置uploadUrl属性。 允许你添加、移除和追加文件。添加的文件可以生成预览图。 插件外部依赖需求
最新版本的jQuery 大多数现代浏览器都支持HTML5(inputs和FileReader AP),CSS3和jQuery。对于IE浏览器,必须是IE10以上的版本。IE9及以下的版本会回退为普通的文件上传组件,并且不支持选择多个文件和HTML 5 FileReader API。 AJAX上传需要浏览器支持HTML5 FormData和XHR2 (XMLHttpRequest 2)。大多数现代浏览器都支持FormData和XHR2。在不支持这些特性的浏览器中将会回退为普通的文件上传组件。 引用一般情况下,我们需要引入下面两个文件,插件才能正常使用: bootstrap-fileinput/css/fileinput.min.cssbootstrap-fileinput/js/fileinput.min.js 简单的界面效果如下所示,和众多上传文件控件一样,可以接受各种类型的文件。当然,我们也可以指定具体接受的文件类型等功能。 如果需要考虑中文化,那么还需要引入文件: bootstrap-fileinput/js/fileinput_locale_zh.js 下载文件地址: https://github.com/kartik-v/bootstrap-fileinput http://download.csdn.net/detail/q383965374/9879093 下载解压后得到相关资源文件。 我们在自己的项目资源文件夹中新建目录bootstrap-fileinput,把相关文件放进去。如图所示: 在index.jsp中引用文件代码如下:
<link type="text/css" rel="stylesheet" href="/res/bootstrap-fileinput/css/fileinput.css" /> <script type="text/javascript" src="/res/bootstrap-fileinput/js/fileinput.js"></script> <script type="text/javascript" src="/res/bootstrap-fileinput/js/zh.js"></script> 初始化插件// initialize with defaults $("#input-id").fileinput(); // with plugin options $("#input-id").fileinput({'showUpload':false,'previewFileType':'any'});? ? ? ? ? #input-id是文件上传input元素的ID标识符(例如:type = file)。 你也可以直接通过HTML5 data属性来初始化插件。
<input id="input-id" type="file" class="file" data-preview-file-type="text" > ? ? ? ?? 或者使用封装方法 html代码 <div class="row" style="height: 500px"> <input id="file-Portrait" type="file"> </div> JS代码
//初始化fileinput控件(第一次初始化) function initFileInput(ctrlName,uploadUrl) { var control = $('#' + ctrlName); control.fileinput({ language: 'zh',//设置语言 uploadUrl: uploadUrl,//上传的地址 allowedFileExtensions : ['jpg','png','gif'],//接收的文件后缀 showUpload: false,//是否显示上传按钮 showCaption: false,//是否显示标题 browseClass: "btn btn-primary",//按钮样式 previewFileIcon: "<i class='glyphicon glyphicon-king'></i>",}); } //初始化fileinput控件(第一次初始化) initFileInput("file-Portrait","/User/EditPortrait"); ?配置参数
// for image files initialPreview: [ "<img src='/images/desert.jpg' class='file-preview-image' alt='Desert' title='Desert'>","<img src='/images/jellyfish.jpg' class='file-preview-image' alt='Jelly Fish' title='Jelly Fish'>",],// for text files initialPreview: "<div class='file-preview-text' title='NOTES.txt'>" + "This is the sample text file content upto wrapTextLength of 250 characters" + "<span class='wrap-indicator' onclick='$("#show-detailed-text").modal("show")' title='NOTES.txt'>[…]</span>" + "</div>" // for other files initialPreview: "<div class='file-preview-text'>" + "<h2><i class='glyphicon glyphicon-file'></i></h2>" + "Filename.xlsx" + "</div>" initialPreviewCount:类型int。被添加到选择的文件的初始化预览图的数量。当overwriteInitial属性设置为false时,该参数可以显示正确的文件标题。 initialPreviewDelimiter:类型string。用于分割初始化预览图内容的分割符。只有在initialPreview属性传入的参数是字符串而不是数组时可用。默认值是:*$$*。
- `caption`: _string_,the caption or filename to display for each initial preview item content. - `width`: _string_,the CSS width of the image/content displayed. - `url`: _string_,the URL for deleting the image/content in the initial preview via AJAX post response. This will default to `deleteUrl` if not set. - `key`: _string|object_,the key that will be passed as data to the `url` via AJAX POST. - `extra`: _object|function_,the extra data that will be passed as data to the initial preview delete url/AJAX server call via POST. This will default to `deleteExtraData` if not set. 下面是配置initialPreviewConfig属性的一个例子。 // setup initial preview with data keys initialPreview: [ "<img src='/images/desert.jpg' class='file-preview-image' alt='Desert' title='Desert'>",// initial preview configuration initialPreviewConfig: [ { caption: 'desert.jpg',width: '120px',url: '/localhost/avatar/delete',key: 100,extra: {id: 100} },{ caption: 'jellyfish.jpg',key: 101,extra: function() { return {id: $("#id").val()}; },} ] 注意:ajax delete操作会通过POST向服务器发送下面的数据: key:在initialPreviewConfig['key']中设置的key值。 通过initialPreviewConfig['extra']或deleteExtraData格式传入的其它作为key: value键值对数据。 initialPreviewShowDelete:是否为每一个由initialPreview插件的预览图创建一个删除按钮。
// change thumbnail footer template layoutTemplates.footer = '<div class="file-thumbnail-footer">n' + ' <div class="file-caption-name">{caption}</div>n' + ' {CUSTOM_TAG_NEW}n' + ' {CUSTOM_TAG_INIT}n' + ' {actions}n' + '</div>'; // set preview template tags previewThumbTags = { '{CUSTOM_TAG_NEW}': '<span class="custom-css">CUSTOM MARKUP</span>','{CUSTOM_TAG_INIT}': ' ' }; 上面只是该文件上传插件一部分的属性,要查看完整的属性和可用方法,可以查看: https://github.com/kartik-v/bootstrap-fileinput/ 也可以查看 fileinput.js中的$.fn.fileinput.defaults方法,如图: JSP页面<%@ include file="./include/header.jsp"%> <%@ taglib uri="com.data.web.view.function" prefix="cf" %> <style> /*uploadfive上传插件背景按钮图样式*/ .upload-image { ? ? height: 200px; ? ? width: 200px; ? ? background-image: url(/res/assets/img/demoUpload.jpg); ? ? background-color: white; ? ? background-repeat: no-repeat; ? ? background-size: contain; ? ? background-origin: content-box; ? ? background-position: center; ? ? background-size: contain; ? ? background-origin: content-box; } </style> ? ? ? ? <div id="page-wrapper"> ? ? ? ? ? ? <div id="page-inner"> ? ? ? ? ? ? ? ? <div class="row"> ? ? ? ? ? ? ? ? ? ? <div class="col-md-12"> ? ? ? ? ? ? ? ? ? ? ? ? <h1 class="page-header"> ? ? ? ? ? ? ? ? ? ? ? ? ? ? 多张(动态)图片上传 <small>Uploadify</small> ? ? ? ? ? ? ? ? ? ? ? ? </h1> ? ? ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? <!-- /. ROW ?--> ? ? ?<form class="form-horizontal" id="base"> ? ? ? ? ? ? ? ? ?<input type="text" value="${pic.id}" id="id" name="id" hidden/> ? ? ? ? ? ? ? ? <div class="form-group"> ? ? ? ? ? ? ? ? ? ? <label for="name" class="col-sm-2 control-label">名称:</label> ? ? ? ? ? ? ? ? ? ? <div class="col-sm-10"> ? ? ? ? ? ? ? ? ? ? ? ? <input type="text" class="form-control" id="name" name="name" value="${pic.name}" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?placeholder=""> ? ? ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? <div class="form-group "> ? ? ? ? ? ? ? ? ? ? <label class="col-sm-2 control-label">描述:</label> ? ? ? ? ? ? ? ? ? ? <div class="col-sm-10"> ? ? ? ? ? ? ? ? ? ? ? ? <textarea id="description" name="description" class="form-control" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rows="8">${pic.description}</textarea> ? ? ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? <div class="form-group"> ? ? ? ? ? ? ? ? <label class="col-sm-2 control-label">图片上传:</label> ? ? ? ? ? ? ? ? <div class="col-sm-10"> ? ? ? ? <input id="file-0a" class="file file-loading" type="file" multiple? ? ? ? ? ? ?data-min-file-count="1" name="upload_file" > ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? ? <div class="form-group " id="pics"> ? ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? <div class="form-group"> ? ? ? ? ? ? ? ? ? ? <div class="col-sm-6 col-sm-offset-2"> ? ? ? ? ? ? ? ? ? ? ? ? <button type="button" class="btn btn-default cancel" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? data-dismiss="modal">取消 ? ? ? ? ? ? ? ? ? ? ? ? </button> ? ? ? ? ? ? ? ? ? ? ? ? <button type="button" class="btn btn-primary save" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? data-loading-text="Saving...">确认 ? ? ? ? ? ? ? ? ? ? ? ? </button> ? ? ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ?</form> ? ? ? ? ? ? ? ? ? <!-- /. ROW ?--> ? ? ? ? ? ? </div> ? ? ? ? ? ? <!-- /. PAGE INNER ?--> ? ? ? ? </div> ? ? ? ? <!-- /. PAGE WRAPPER ?--> ? ?? ? ? ? ?? ? ? ? ?? ?<%@ include file="./include/footer.jsp"%> ?<link type="text/css" rel="stylesheet" href="/res/bootstrap-fileinput/css/fileinput.css" /> <script type="text/javascript" src="/res/bootstrap-fileinput/js/fileinput.js"></script> <script type="text/javascript" src="/res/bootstrap-fileinput/js/zh.js"></script> <script type="text/javascript"> /** ?* jQuery form 扩展获取数据 ?*/ $.fn.formGet = function(opts) { opts = $.extend({},opts); var data = {},? els = opts.formGroup ? this.find('[form-group="' + opts.formGroup + '"]') : this.find('[name]'); if (!els || !els.length) { ? return data; } var fnSetValue = (function(emptyToNull) { ? return emptyToNull ? function(obj,propertyChain,value,allowMulti) { ? ? value !== '' && _fnObjectSetPropertyChainValue(obj,allowMulti) ? } : _fnObjectSetPropertyChainValue })(opts.emptyToNull); els.each(function() { ? var $this = $(this),? ? type = $this.attr('type'),? ? name = $this.attr('name'),// 可能为属性链 ? ? tag = this.tagName.toLowerCase(); ? if (tag == 'input') { ? ? if (type == 'checkbox') { ? ? ? var v = $(this).val(); ? ? ? if (v == 'on' || !v) { ? ? ? ? fnSetValue(data,name,$(this).prop('checked')); ? ? ? } else { ? ? ? ? $(this).prop('checked') && fnSetValue(data,v,true); ? ? ? } ? ? } else if (type == 'radio') { ? ? ? this.checked && fnSetValue(data,$this.val()); ? ? } else { ? ? ? fnSetValue(data,$this.val()); ? ? } ? } else if ('|select|textarea|'.indexOf('|' + tag + '|') > -1) { ? ? fnSetValue(data,$this.val()); ? } else { ? ? fnSetValue(data,$.trim($this.text())); ? } }); return data; }; /** ? ?* 内部私有方法 ? ?*/ ? var _fnObjectGetPropertyChainValue = function(obj,propertyChain) { ? ? /* 获取属性链的值 */ ? ? if (!obj) return; ? ? if (!propertyChain) return obj; ? ? var property,? ? ? chains = propertyChain.split('.'),? ? ? i = 0,? ? ? len = chains.length; ? ? for (; ? ? ? (property = chains[i]) && i < len - 1; i++) { ? ? ? if (!obj[property]) return; ? ? ? obj = obj[property]; ? ? } ? ? return obj[property]; ? },? _fnObjectSetPropertyChainValue = function(obj,allowMulti) { ? ? /* 设置属性链的值 */ ? ? if (!obj || !propertyChain) return; ? ? var property,? ? ? chainObj = obj,? ? ? len = chains.length; ? ? for (; ? ? ? (property = chains[i]) && i < len - 1; i++) { ? ? ? if (!chainObj[property]) { ? ? ? ? chainObj[property] = {}; ? ? ? } ? ? ? chainObj = chainObj[property]; ? ? } ? ? // 改进版:checkbox的多选可以组合为数组 ? ? if (!allowMulti || chainObj[property] === undefined) { ? ? ? chainObj[property] = value; ? ? } else { ? ? ? var pv = chainObj[property]; ? ? ? if ($.isArray(pv)) { ? ? ? ? pv.push(value); ? ? ? } else { ? ? ? ? chainObj[property] = [pv,value]; ? ? ? } ? ? } ? ? return obj; ? }; ? ?? //初始化插件 $("#file-0a").fileinput({ uploadUrl : "/upload",//上传文件的url--对应后台的接收controller language: 'zh',//设置语言 allowedFileExtensions : [ 'jpg','gif' ],overwriteInitial : false,dropZoneEnabled: false,//禁用dropZone区域,选择图片后才显示预览区域(推荐) //showPreview: false,//隐藏dropZone和预览区 //showBrowse: false,//隐藏选择框的选择按钮 //showUpload: false,//隐藏选择框的上传按钮 //showCaption: false,//隐藏选择栏的input //captionClass:'col-sm-10',//在标题容器上额外的class //previewClass:'col-sm-10',//在预览容器上额外的class //mainClass:'col-sm-10',//添加在文件上传主容器额外的class maxFileSize : 2000,//上传文件最大的尺寸 maxFilesNum : 3,//上传最大的文件数量 initialCaption: "请上传图片",//文本框初始话value //allowedFileTypes: ['image','video','flash'],slugCallback : function(filename) { return filename.replace('(','_').replace(']','_'); } }); //上传成功后回调函数 $('#file-0a').on('fileuploaded',function(event,data,previewId,index) { debugger; var form = data.form,files = data.files,extra = data.extra,response = data.response,reader = data.reader; console.log(response);//打印出返回的json console.log("${hostname}"+response.result);//打印出路径 $("#pics").append('<input type="hidden" class="imagePaths" name="imagePaths_'+index+'.filePath" ?value="'+"${hostname}"+response.result+'">');? }); ?? ? ? $(document).ready(function () { ? ? ? ? /*END-保存表单-END*/ ? ? ? ? $('button.save').on('click',function () { ? ? ? ? ? ? debugger; ? ? ? ? ? ? var data = $('#base').formGet(); ? ? ? ? ? ? var imagePaths = new Array(); ? ? ? ? ? ? var length=$('.imagePaths').length; ? ? ? ? ? ?for(var i=0;i<length;i++){ ? ? ? ? ? ?var index=eval('data.imagePaths_'+i); ? ? ? ? ? ? imagePaths.push(index); ? ? ? ? ? ? } ? ? ? ? ? ? data.imagePaths=imagePaths; ? ? ? ? ? ? $.ajax({ ? ? ? ? ? ? ? ? type: "POST",? ? ? ? ? ? ? ? url: "/pic/save",? ? ? ? ? ? ? ? contentType: "application/json",? ? ? ? ? ? ? ? data: JSON.stringify(data),? ? ? ? ? ? ? ? success: function (result) { ? ? ? ? ? ? ? ? ? ? console.log(result); ? ? ? ? ? ? ? ? ? ? if (!result.code)? ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? alert(result.data); ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? alert(result.msg); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? },? ? ? ? ? ? ? ? error: function (result) { ? ? ? ? ? ? ? ? ? ? alert("出错了,请稍后重试"); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }); ? ? ? ? }); ? ? }); </script> </body> </html> 返回信息辅助实体类AjaxResult.javapackage com.test.util; import org.springframework.data.annotation.Transient; /** * AjaxResult * * 标准化的ajax响应,取代之前直接返回结果的方式。 * */ public class AjaxResult { @Transient public static final int CODE_SUCCESS = 1; @Transient public static final int CODE_FAILURE = 0; @Transient public static final AjaxResult RESULT_ERROR = new AjaxResult( CODE_FAILURE,"执行出错了",null); @Transient public static final AjaxResult RESULT_SUCCESS = new AjaxResult( CODE_SUCCESS,null,null); @Transient public static final AjaxResult RESULT_INVAILD_PARAMETER = new AjaxResult( CODE_FAILURE,"参数格式不正确",null); private int code = CODE_FAILURE; private String error; private Object result; public static AjaxResult resultError(String error) { return new AjaxResult(CODE_FAILURE,error,null); } public static AjaxResult resultSuccess(Object result) { return new AjaxResult(CODE_SUCCESS,result); } /** * @param code * @param error * @param result */ public AjaxResult(int code,String error,Object result) { super(); this.code = code; this.error = error; this.result = result; } /** * @return the code */ public int getCode() { return code; } /** * @param code * the code to set */ public void setCode(int code) { this.code = code; } /** * @return the error */ public String getError() { return error; } /** * @param error * the error to set */ public void setError(String error) { this.error = error; } /** * @return the result */ public Object getResult() { return result; } /** * @param result * the result to set */ public void setResult(Object result) { this.result = result; } } JSONResult.javapackage com.test.util; /** * JSONResult * 标准化的JSON响应 * * <pre> * {@link JSONResult#success(Object)} * {@link JSONResult#error(String)} * </pre> * * */ public class JSONResult { /** * 成功的代码 */ public static final int CODE_SUCCESS = 0; /** * 错误的代码,可根据错误类型进行详细分类 */ public static final int CODE_ERROR = -1; /** * 空白的成功响应 */ public static final JSONResult RESULT_SUCCESS_NO_DATA = new JSONResult(CODE_SUCCESS,null); private int code; private String msg; private Object data; /** * 创建一个成功的响应 * * @param data * @return */ public static JSONResult success(Object data) { return new JSONResult(CODE_SUCCESS,data); } /** * 创建一个错误的响应 * * @param msg * @return */ public static JSONResult error(String msg) { return new JSONResult(CODE_ERROR,msg,null); } /** * @param code * @param msg * @param data */ public JSONResult(int code,String msg,Object data) { this.code = code; this.setMsg(msg); this.data = data; } public int getCode() { return code; } public JSONResult setCode(int code) { this.code = code; return this; } public Object getData() { return data; } public JSONResult setData(Object data) { this.data = data; return this; } public String getMsg() { return msg; } public JSONResult setMsg(String msg) { this.msg = msg; return this; } } Pic.javapackage com.test.domain.entity; import java.util.List; public class Pic { private String id; private String name; private String description; private List<Image> imagePaths; // 图片 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public List<Image> getImagePaths() { return imagePaths; } public void setImagePaths(List<Image> imagePaths) { this.imagePaths = imagePaths; } } Image.javapackage com.test.domain.entity; /** * 图片 Image */ public class Image { private String title; //名称 private String description; //描述 private String filePath; //文件地址 public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public Image() { } /** * @param title * @param filePath */ public Image(String title,String filePath) { this.title = title; this.filePath = filePath; } } 页面路由控制器IndexController.javapackage com.test.web.controller; import java.io.IOException; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.test.domain.entity.Pic; import com.test.util.JSONResult; /** ?* IndexController ?*? ?*? ?*/ @Controller public class IndexController { @RequestMapping("/") public String index(Model model) throws IOException { ? ? ? ? ? model.addAttribute("hostname","http://127.0.0.1:8080/"); return "/index"; } @RequestMapping("/pic/save") @ResponseBody public JSONResult saveMigrateLine(@RequestBody Pic pic) { //保存pic记录 //int result = save(pic); int result =1; return result > 0 ? JSONResult.success("保存成功") :JSONResult.error("保存失败!"); } } 文件上传接收控制器UploadController.javapackage com.test.web.controller; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.test.util.AjaxResult; /** * 通用的上传(保存到本地服务器) * */ @Controller public class UploadController { private final Logger logger = LoggerFactory.getLogger(getClass().getName()); /** * 上传到服务器,文件名称随机生成(基本可以保证不重复) * * @param request * @param response * @return AjaxResult 存储的文件的相对路径 * @throws IOException */ @RequestMapping("/upload") @ResponseBody public AjaxResult upload(HttpServletRequest request,HttpServletResponse response) throws IOException { try { String filePath="/uploadfile"; //获取文件存储路径 (虚拟目录映射为本机服务器的实际目录) String path = request.getSession().getServletContext().getRealPath(filePath); //如果保存在ROOT里,重新发包后静态资源会丢失,所以保存在ROOT包的上级路径webapp中 path=path.replace("ROOT",""); String fileNameResult =""; // 判断enctype属性是否为multipart/form-data boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (!isMultipart) throw new IllegalArgumentException( "上传内容不是有效的multipart/form-data类型."); // Create a factory for disk-based file items DiskFileItemFactory factory = new DiskFileItemFactory(); // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); // Parse the request List<?> items = upload.parseRequest(request); Iterator iter = items.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (item.isFormField()) { // 如果是普通表单字段 String name = item.getFieldName(); String value = item.getString(); // ... } else { // 如果是文件字段 String fieldName = item.getFieldName(); String fileName = item.getName(); String contentType = item.getContentType(); boolean isInMemory = item.isInMemory(); long sizeInBytes = item.getSize(); String fileExt = fileName.substring(fileName.lastIndexOf('.')); String fileNameNew =getFileNameNew()+fileExt; fileNameResult=fileNameNew; //保存到本地 InputStream uploadedStream = item.getInputStream(); savePic(path,uploadedStream,fileNameNew); uploadedStream.close(); } } return AjaxResult.resultSuccess(filePath+"/"+fileNameResult); } catch (FileUploadException e) { logger.warn(e.getMessage(),e); return AjaxResult.resultError(e.getMessage()); } } private void savePic(String path,InputStream inputStream,String fileName) { OutputStream os = null; try { // 2、保存到临时文件 // 1K的数据缓冲 byte[] bs = new byte[1024]; // 读取到的数据长度 int len; // 输出的文件流保存到本地文件 File tempFile = new File(path); if (!tempFile.exists()) { tempFile.mkdirs(); //如果图片是保存在ROOT项目外,首次创建目录,tomcat加载需要时间,所以需要延迟10秒 Thread.sleep(10000); } os = new FileOutputStream(tempFile.getPath() + File.separator + fileName); // 开始读取 while ((len = inputStream.read(bs)) != -1) { os.write(bs,len); } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { // 完毕,关闭所有链接 try { os.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } private String getFileNameNew() { SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS"); return fmt.format(new Date()); } } 目前上传的文件是接收后保存到本地服务器中,如果要上传到远程服务器或者七牛云等,只需要修改UploadController.java即可。 这里只给出了?uploadify 上传图片的案例。 但其实 这个DEMO也可以用于上传 zip等文件。 只需要稍微调整jsp页面把图片显示去掉即可。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- twitter-bootstrap – Bootstrap中的两个并排表
- Reactjs+BootStrap开发自制编程语言Monkey的编译器:创建简易
- bash – 使用CUPS打印前后运行命令?
- 使用AngularJS和jsPlumb(在AngularJS控制器中使用jsPlumb函
- shell 文件内容替换 sed用法
- shell 学习四十二天----使用 touch 更新文件时间
- gVim安装vim-template插件后提示Undefined variable vim_te
- Scala – 用于不可变集合的hashCode缓存
- ‘=?’的含义是什么?在angularJS指令隔离范围声明?
- Bootstrap基本模板的使用和理解1