学习笔记----webuploader上传文件

本文介绍如何在SpringMVC+MyBatis+Spring框架中实现文件上传功能,涵盖前端JS和后端Java代码示例,特别关注文件上传组件WebUploader的配置与使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.说明

本人在项目中使用的是springmvc+mybatis+spring框架下使用上传文件的功能,关键在于前端js和后台代码的理解和编写,代码不能单独拿来运行,是在理解的基础上,修改为适合自己开发环境的。

2.前端代码:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE HTML>
<html>
<head>
<jsp:include page="common/header.jsp"/>
<!--需要引入webuploader.css文件  -->
<link href="${pageContext.request.contextPath }/lib/webuploader/0.1.5/webuploader.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="page-container">
	<form method="post" class="form form-horizontal" id="form-goods-add">
		<input name="id" type="hidden" value="${versioUpdate.id }" />
		 <div class="row cl">
			<label class="form-label col-xs-4 col-sm-2"><span class="c-red">*</span>apk名字:</label>
			<div class="formControls col-xs-8 col-sm-9">
				<input type="text" class="input-text"  readonly="readonly" value="${versionUpdate.apkName }" placeholder="" maxlength="100" name="apkName" id="apkName">
			</div>
		</div>
	    <div class="row cl">
			<label class="form-label col-xs-4 col-sm-2"><span class="c-red">*</span>apk版本号:</label>
			<div class="formControls col-xs-8 col-sm-9">
				<input type="text" class="input-text" value="${versionUpdate.version }" placeholder="" maxlength="100" name="version">
			</div>
		</div>

       <div class="row cl">
			<label class="form-label col-xs-4 col-sm-2"><span class="c-red">*</span>apk简介:</label>
			<div class="formControls col-xs-8 col-sm-9">
				<input type="text" class="input-text" value="${versionUpdate.content }" placeholder="" maxlength="100" name="content">
			</div>
		</div>
		<!-- apk上传文件 -->
		 <div class="row cl">
		    <input name="apkUrl" id="apkUrl" type="hidden"  />
			<label class="form-label col-xs-4 col-sm-2"><span class="c-red">*</span>apk上传:</label>
			<div class="btns"  >
		        <!-- 这个picker是用来选择文件的 -->
		        <div id="picker" style="display:inline"></div>
		        <!-- 如果未使用自动上传,点击按钮可以触发上传事件 -->
		        <div id="ctlBtn" class="uploadbutton" ></div>
		        <!-- 存放需上传的文件信息-->
		        <div id="thelist" class="uploader-list"></div>
		    </div>
		    <!-- 上传文件的遮罩,本身未添加该div,因说到上传文件时,如果直接进行其他操作会有什么影响,因此添加遮罩和提示信息避免误操作-->
		    <div id="uploadbg"></div>
		    <!-- 文件上传时的提示信息处理,包含进度条等信息-->
		    <div id="uploadshow">
		        <font color='#EE7621'>
		        <label class="state" id="waitUpload">等待上传...</label>
		        </font>
		        <div class="progress"  style="position: absolute;height:30px;width:300px;">
		            <p id="progressUpload" style="top:0px;position: absolute;transform: translate(0%,0%);font-size: 10px;height:15px;width:0px;background-color:#E0FFFF;text-align:center">0%
		            </p>
		        </div>
		    </div>
		</div>
		
			<div class="row cl">
			<div class="col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-2">
				<button class="btn btn-primary radius" type="submit"><i class="Hui-iconfont"></i> 保存</button>
				<button onClick="layer_close();" class="btn btn-default radius" type="button">  取消  </button>
			</div>
		</div>
	</form>
</div>

<jsp:include page="common/footer.jsp"/>

<!--请在下方写此页面业务相关的脚本-->
<script type="text/javascript" src="${pageContext.request.contextPath }/lib/My97DatePicker/4.8/WdatePicker.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/lib/jquery.validation/1.14.0/jquery.validate.js"></script> 
<script type="text/javascript" src="${pageContext.request.contextPath }/lib/jquery.validation/1.14.0/validate-methods.js"></script> 
<script type="text/javascript" src="${pageContext.request.contextPath }/lib/jquery.validation/1.14.0/messages_zh.js"></script>
<!--需要引入webuploader.min.js文件  -->
<script type="text/javascript" src="${pageContext.request.contextPath }/lib/webuploader/0.1.5/webuploader.min.js"></script> 
<script type="text/javascript" src="${pageContext.request.contextPath }/lib/ueditor/1.4.3/ueditor.config.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/lib/ueditor/1.4.3/ueditor.all.min.js"> </script>
<script type="text/javascript" src="${pageContext.request.contextPath }/lib/ueditor/1.4.3/lang/zh-cn/zh-cn.js"></script>
<style type="text/css">
/*上传文件的背景修饰 */
#uploadbg {
    display: none;
    position: absolute;
    top: 0%;
    left: 0%;
    width: 100%;
    height: 100%;
    background-color: #EBEBEB;
    z-index: 1001;
    -moz-opacity: 0.7;
    opacity: .70;
    filter: alpha(opacity = 70);
}

#uploadshow {
    display: none;
    position: absolute;
    top: 45%;
    left: 30%;
    width: 40%;
    height: 10%;
    padding: 8px;
    border: 0px solid #F1F1F1;
    background-color: #F1F1F1;
    z-index: 1002;
    overflow: auto;
}
</style>
<script type="text/javascript">

/*********************************WebUpload 单文件上传 begin*****************************************/
//遮罩的方法
function showdiv() {    
            $('#uploadbg').css("display","block");
            $('#uploadshow').css("display","block");
        }
function hidediv() {
            $('#uploadbg').css("display","none");
            $('#uploadshow').css("display","none");
        }

var $list = $("#thelist");//定义上传文件显示的位置
var fileSize = '';//获取文件大小
var lastModiDate = '';//获取文件最后修改日期

//初始化Web Uploader
var uploader = WebUploader.create({
    swf: '${pageContext.request.contextPath }/lib/webuploader/0.1.5/Uploader.swf',//swf文件路径
    server: "${pageContext.request.contextPath }/backend/common/uploadApkFile",// 文件接收后台路径。
    pick: {
               id: '#picker',
               name:"multiFile",  //这个地方 name 没什么用,虽然打开调试器,input的名字确实改过来了。但是提交到后台取不到文件。如果想自定义file的name属性,还是要和fileVal 配合使用。
               label: '选择apk',
               multiple:false   //默认为true,true表示可以多选文件,HTML5的属性
          },
    formData: {//上传时提交自身需要的字段并传递到后台。
        "status":"file",
        "uploadNum":"0000004730",
        "existFlg":'false'
    },
    fileVal:'multiFile',
    resize: false,
    auto:true ,//是否自动上传
    threads:3,//上传并发数。允许同时最大上传进程数。
    chunked: true,  //分片处理
    chunkSize: 10 * 1024 * 1024, //每片10M
    accept: {// 只允许选择apk文件
        title: 'apk文件',
        extensions: 'apk'//允许的文件后缀
      //  mimeTypes: 'image/*'
        },
    //fileNumLimit:1,//最大选择要上传的文件总数  
    disableGlobalDnd: true // 禁掉全局的拖拽功能。 
});

// //移除文件的方法,未进行后端删除的添加
// function deleFile(fileId) {
//     uploader.removeFile(fileId,true);//调用方法删除文件队列
//     $('#'+fileId).remove();//清理页面元素
// };

//上传按钮点击时触发
$("#ctlBtn").on("click", function() {
    uploader.upload();
});

//当有文件添加进来的时候
uploader.on( 'fileQueued', function( file ) {
    fileSize = file.size;//为文件大小赋值
   // deleFile(file.id);
    var timestamp = Date.parse(new Date(file.lastModifiedDate));
    timestamp = timestamp / 1000;
    lastModiDate = timestamp;//获取文件最后修改时间,并转换成时间戳
    /* $list.append( '<div id="' + file.id + '" class="item" style="display:inline">' +
        '<h4 class="info" style="display:inline">' + file.name + '</h4>  <div class="uploadbutton" id=\'deleBut_'+file.id+'\' onclick="deleFile(\''+file.id+'\');" >移除</div>' +
    '</div>' ); */// 在文件上传的位置添加文件信息,可以修改
    showdiv();//因为设置的是自动上传,所以添加进来后,自动调用遮罩
});

//当某个文件的分块在发送前触发,主要用来询问是否要添加附带参数,大文件在开起分片上传的前提下此事件可能会触发多次。
uploader.on('uploadBeforeSend', function (obj, data, headers) {
    data.lastModiDate = lastModiDate;//为formData赋值
    data.fileSize = fileSize;
});

//文件上传过程中创建进度条实时显示。
uploader.on( 'uploadProgress', function( file, percentage ) {
    $progress = $('#waitUpload');
    $percent = $('#progressUpload');
    $progress.text('正在上传,在此期间不要做其他操作,请耐心等待...');
    $percent.css( 'width', percentage * 100 + '%' );
    $percent.text((percentage * 100).toFixed(2) + '%');
});

//完成上传,不管成功或者失败,先把遮罩删除。
uploader.on( 'uploadComplete', function( file ) {
    hidediv();
});

uploader.on("error", function (type) {
    if (type == "Q_TYPE_DENIED") {
        layer.msg("请上传apk格式文件");
    } 
});
// 文件上传成功之后进行的处理。
uploader.on( 'uploadSuccess', function( file ,data  ) {
    if(data.files){
    	//为input的id为apkUrl填充文件上传成功后返回文件的路径值和文件名
		$("#apkUrl").val(data.files[0].url);
		$("#apkName").val(data.files[0].fileName);
	}
    $success = $('#waitUpload');
    $success.text('上传成功');
});

// 文件上传失败
uploader.on( 'uploadError', function( file ) {
    $error = $('#waitUpload');
    $error.text('上传失败');
});

//日期格式化成时间字符串
Date.prototype.format = function(fmt) { 
    var o = { 
       "M+" : this.getMonth()+1,                 //月份 
       "d+" : this.getDate(),                    //日 
       "h+" : this.getHours(),                   //小时 
       "m+" : this.getMinutes(),                 //分 
       "s+" : this.getSeconds(),                 //秒 
       "q+" : Math.floor((this.getMonth()+3)/3), //季度 
       "S"  : this.getMilliseconds()             //毫秒 
   }; 
   if(/(y+)/.test(fmt)) {
           fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); 
   }
    for(var k in o) {
       if(new RegExp("("+ k +")").test(fmt)){
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
        }
    }
   return fmt; 
};  
/*********************************WebUpload 单文件上传 end*******************************************/

$(function(){
	//表单验证
	$("#form-goods-add").validate({
		rules:{
			apkName:{
				required:true
			},version:{
				required:true
			},content:{
				required:true
			}
			
		},
		onkeyup:false,
		success:"valid",
		submitHandler:function(form){
			$(form).ajaxSubmit({url:'save',type:'POST',dataType:'JSON',success:function(data){
					if(data.success){
						var index = parent.layer.getFrameIndex(window.name);
						parent.freshTable();
						parent.layer.close(index);
					}
				}
			});
			return false;
		}
	});

});
</script>
</body>
</html>


3.后端代码:

上传文件的核心代码:

package com.ie9e.framework.system.controller;

import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.ie9e.framework.common.constants.Global;
import com.ie9e.framework.common.controller.BaseController;
import com.ie9e.framework.system.entity.TSAttachment;
import com.ie9e.framework.system.model.FileMeta;
import com.ie9e.framework.system.service.AttachmentService;
import com.ie9e.framework.utils.ResourceUtil;

import net.coobird.thumbnailator.Thumbnails;

/**
 * 通用业务处理
 * 
 * @author 一叶扁舟(skiff)
 * 
 */
@Controller
@RequestMapping("${namespace.backend}/common")
public class CommonController extends BaseController {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(CommonController.class);

	@Autowired
	@Qualifier("attachmentService")
	private AttachmentService attachmentService;

	@RequestMapping("error/403")
	public String e403() {
		return PRE_BACK + "common/403";
	}

	@RequestMapping("error/404")
	public String e404() {
		return PRE_BACK + "common/404";
	}

	@RequestMapping("view/{id}")
	public void getImageView(HttpServletRequest request, HttpServletResponse response, @PathVariable Long id)
			throws ServletException, IOException {

		String url = attachmentService.getAttachmentWebUrl(id);
		response.sendRedirect(url);
	}

	@RequestMapping("/upload")
	@ResponseBody
	public Map<String, Object> upload(MultipartHttpServletRequest request, HttpServletResponse response) {

		Iterator<String> itr = request.getFileNames();
		MultipartFile multipartFile = null;
		LinkedList<FileMeta> files = new LinkedList<FileMeta>();
		FileMeta fileMeta = null;

		while (itr.hasNext()) {

			multipartFile = request.getFile(itr.next());

			if (files.size() >= 10) {
				files.pop();
			}
			fileMeta = new FileMeta();
			fileMeta.setFileName(multipartFile.getOriginalFilename());
			fileMeta.setFileSize(multipartFile.getSize() / 1024 + " Kb");
			fileMeta.setFileType(multipartFile.getContentType());
			try {
				TSAttachment attachment = attachmentService.saveAttachment(multipartFile);
				//				fileMeta.setBytes(multipartFile.getBytes());
				fileMeta.setId(attachment.getId());
				fileMeta.setUrl(attachmentService.getAttachmentWebUrl(attachment));
			} catch (IOException e) {
				e.printStackTrace();
			}
			files.add(fileMeta);
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("files", files);
		return params;
	}

	
	/**  
	 * 方法功能说明:上传apk方法    
	 * @参数: @param request
	 * @参数: @param response
	 * @参数: @return      
	 * @return String     
	 * @throws  
	 */ 
	@RequestMapping("/uploadApkFile")
	@ResponseBody
	public Map<String, Object> uploadApkFile(MultipartHttpServletRequest request, HttpServletResponse response) {

		Iterator<String> itr = request.getFileNames();
		MultipartFile multipartFile = null;
		LinkedList<FileMeta> files = new LinkedList<FileMeta>();
		FileMeta fileMeta = null;

		while (itr.hasNext()) {

			multipartFile = request.getFile(itr.next());

			if (files.size() >= 10) {
				files.pop();
			}
			fileMeta = new FileMeta();
			fileMeta.setFileName(multipartFile.getOriginalFilename());
			fileMeta.setFileSize(multipartFile.getSize() / 1024 + " Kb");
			fileMeta.setFileType(multipartFile.getContentType());
			try {
				//将apk文件上传到指定的文件夹中,然后返回该文件的路径
			   String pakUrl = 	uploadApkFileToFolder(multipartFile);
				fileMeta.setUrl(pakUrl.replaceAll("\\\\", "/"));
				String fileAllName = multipartFile.getOriginalFilename();
				//文件后缀的长度
				int extLength =getFileType(fileAllName).length();
				//文件名,不带文件后缀的
				String  fileName = fileAllName.substring(0, fileAllName.length() - extLength - 1);
				fileMeta.setFileName(fileName);
			} catch (IOException e) {
				e.printStackTrace();
			}
			files.add(fileMeta);
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("files", files);
		return params;
	}
	
	

	/**  
	 * 方法功能说明:    将apk文件上传到服务器中的指定文件夹中
	 * @参数: @param file
	 * @参数: @param isThumb
	 * @参数: @param safety
	 * @参数: @return
	 * @参数: @throws IOException      
	 * @return String     
	 * @throws  
	 */ 
	public String uploadApkFileToFolder(MultipartFile file) throws IOException {
		String realFileName = file.getOriginalFilename();
		String md5 = null;
		//文件的后缀
		String ext = getFileType(realFileName).toLowerCase();
		long curTime = System.currentTimeMillis();
		//String saveFileName = UUID.randomUUID().toString() + "." + ext;
		//获取上传的文件夹路径,如果文件夹不存在就创建
		String relativePath = getFileUploadPath(curTime) + realFileName;
		String realPath = ResourceUtil.getSysPath()+ relativePath;
		byte[] bts = file.getBytes();

		File realFile = new File(realPath);
		if(!realFile.getParentFile().exists()){
			realFile.getParentFile().mkdirs();
		}
		//上传文件
	    FileUtils.writeByteArrayToFile(realFile, bts);
		return relativePath;
	}
	

	/**  
	 * 方法功能说明:   计算附件上传的路径 
	 * @参数: @param datetime
	 * @参数: @param safety
	 * @参数: @return      
	 * @return String     
	 * @throws  
	 */ 
	private static String getFileUploadPath(long datetime) {
		Date date = new Date(datetime);
		String dic = null;
		dic = Global.UPLOAD_APK_VERSION_UPDATE_FOLDER + ResourceUtil.getSeparator() + DateFormatUtils.format(date, "yyyyMM");

		File folder = new File(dic);
		if (!folder.exists()) {
			folder.mkdirs();
		}
		return dic + ResourceUtil.getSeparator();
	}

	
	/**  
	 * 方法功能说明:   获取文件的后缀 
	 * @参数: @param fileName
	 * @参数: @return      
	 * @return String     
	 * @throws  
	 */ 
	public static String getFileType(String fileName) {
		return fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
	}

}


提交到后台保存数据到数据库:

package com.ie9e.framework.system.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.FileItemFactory;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.util.NumberUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.druid.Constants;
import com.github.pagehelper.Page;
import com.ie9e.framework.common.controller.BaseController;
import com.ie9e.framework.common.model.AjaxJson;
import com.ie9e.framework.common.model.PageQuery;
import com.ie9e.framework.system.entity.TSVersionUpdate;
import com.ie9e.framework.system.service.VersionUpdateService;
import com.ie9e.framework.utils.ResourceUtil;
import com.ie9e.framework.view.JSONTableView;

/**  
 * @类功能说明:    处理apk版本更新的控制类,以及apk文件上传的处理
 * @作者: 一叶扁舟
 * @创建时间:2018年1月23日 上午10:35:57  
 * @版本:V1.0  
 */  
@Controller
@RequestMapping("${namespace.backend}/versionupdate")
public class VersionUpdateController extends BaseController {
	private Logger logger = Logger.getLogger(VersionUpdateController.class);
	@Autowired
	@Qualifier("versionUpdateService")
	private VersionUpdateService versionUpdateService;
	
	
	@RequestMapping
	public String versionupdate(HttpServletRequest request) {

		return PRE_BACK + "version-update-list";
	}
	
	
	@RequestMapping("list")
	public JSONTableView list(TSVersionUpdate versionUpdate, PageQuery pageQuery) {
		 Page<TSVersionUpdate> listPage = (Page<TSVersionUpdate>) versionUpdateService.listPage(versionUpdate, pageQuery);
		return new JSONTableView(pageQuery, listPage);
	}
	
	
	
	@RequestMapping("del")
	@ResponseBody
	public AjaxJson del(Long id) {
		AjaxJson ajaxJson = new AjaxJson();
		try {
			versionUpdateService.delVersionUpdate(id);
			ajaxJson.setMsg("删除成功");
		} catch (Exception e) {
		   ajaxJson.setCode("999");
		   ajaxJson.setMsg("删除失败");
		}
		return ajaxJson;
	}
	
	@ResponseBody
	@RequestMapping(value = "save")
	public AjaxJson save(TSVersionUpdate versionUpdate) {
		AjaxJson ajaxJson = new AjaxJson();
		boolean flag=false;
		try {
			//新增apk版本更新信息
			if (versionUpdate.getId() == null) {
				flag=true;
				versionUpdate.setCreateDate(new Date());
				Long userId = ResourceUtil.getUserId();
				versionUpdate.setCreateId(userId);
				versionUpdateService.addVersionUpdate(versionUpdate);
				ajaxJson.setMsg("新增apk版本成功");
			} else {
				versionUpdateService.editVersionUpdate(versionUpdate);
				ajaxJson.setMsg("编辑apk版本成功");
			}
		} catch (Exception e) {
			e.printStackTrace();
			ajaxJson.setSuccess(false);
			if(flag){
				ajaxJson.setMsg("新增apk版本失败");
			}else{
				ajaxJson.setMsg("编辑qpk版本失败");
			}
			
		}
        return ajaxJson;
	}
	
	/**  
	 * 方法功能说明: 对外接口,以json格式返回最新apk版本信息,包括apk版本,apk名字,apk访问的url
	 * @参数: @return      
	 * @return String     
	 * @throws  
	 */ 
	@RequestMapping("getNewestApkVersion")
	@ResponseBody
	public String getNewestApkVersion(){
	String result = versionUpdateService.getNewestApkVersion();
	//result = result.replaceAll("\\", "");
		return result;
	}

	@RequestMapping("edit")
	public String edit(TSVersionUpdate versionUpdate,HttpServletRequest request) {
		if (versionUpdate.getId() != null) {
		versionUpdate = versionUpdateService.getbyId(versionUpdate.getId());
		request.setAttribute("versionUpdate", versionUpdate);
		}
		return PRE_BACK + "version-update-edit";
	}
	

	
}








4.效果截图:



















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值