Web Uploader(上传插件)
摘要:大文件上传也可以支持
官方网址:http://fex.baidu.com/webuploader/
引入资源
使用Web Uploader文件上传需要引入三种资源:JS, CSS, SWF。
<!--引入CSS-->
<link rel="stylesheet" type="text/css" href="webuploader文件夹/webuploader.css">
<!--引入JS-->
<script type="text/javascript" src="webuploader文件夹/webuploader.js"></script>
<!--SWF在初始化的时候指定,在后面将展示-->
Html部分
<div class="layui-form-item"> <!--用来存放文件信息--> <label class="layui-form-label">课程资源</label> <div class="layui-input-block"> <div id="picker">选择文件</div> <!--<button id="ctlBtn" class="layui-btn" type="button">开始上传</button> 改为自动上传--> </div> </div> <div class="layui-form-item"> <div class="layui-input-block"> <!-- 存储上传信息 --> <input type="hidden" name="chapterJson" id="chapterJson"/> <input type="hidden" name="deloldtid" id="deloldtid"/> <!-- 显示上传信息 --> <table id="uploadstatutable" class="layui-table"> <tr> <td>序号</td> <td>文件名</td> <td>课程名称</td> <td>课程编号</td> <td>学分</td> <td>学时</td> <td>大小</td> <td>进度</td> <td>上传状态</td> <td>操作</td> </tr> <tr th:each="chap:${course.chapterList}" th:id="${'row' + chap.id}"> <td th:text="${chapStat.index+1}"></td> <td th:text="${chap.zipname}"></td> <td th:text="${chap.name}"></td> <td th:text="${chap.coursenumber}"></td> <td th:text="${chap.credit}"></td> <td th:text="${chap.courselen/60}"></td> <td th:text="${chap.size}"></td> <td>100.00%</td> <td>已完成</td> <td><a href="javascript:;" class="adelold" th:id="${chap.id}">移除</a></td> </tr> </table> </div> </div>
Js部分
<script th:inline="javascript"> var chapterList = [[${course.chapterList}]];// 已有文件信息 var serialNumber = chapterList.length; // 序号 var fileMd5info = {}; // 上传文件的md5信息 var uuid = [[${uuid}]]; // 站点唯一标识 var uploader; // 上传插件对象 var deloldtid = []; // 需要删除的老课程信息 var allMaxSize = 2000; // 上传大小(单位Mb) var filequee = 0; // 待上传文件数量 $(function () { $("#avatarUpload").click(function () { $("#updateInput").click(); }); $(".adelold").click(function () { var tid = $(this).attr('id'); $("#row" + tid).remove(); deloldtid.push(tid); serialNumber--; }); }) $(function () { uploader = WebUploader.create({ // swf文件路径 swf: basePath + 'static/plugins/webuploadder/flash/Uploader.swf', // 文件接收服务端 。 server: basePath + 'admin/course/fileupload.do', // 选择文件的按钮。可选。 // 内部根据当前运行是创建,可能是input元素,也可能是flash. pick: { id: '#picker', label: '点击选择课程资源', multiple: true }, formData: { 'uuid': uuid// 用作上传站点标识 }, // 是否分片上传 chunked: true, fileSingleSizeLimit: allMaxSize * 1024 * 1024, timeout: 0, accept: {// 限定文件格式 title: 'intoTypes', extensions: 'rar,zip,mp4,flv', mimeTypes: '.rar,.zip,.mp4,.flv' }, // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传! resize: false }); // 开始上传 $("#ctlBtn").on('click', function () { uploader.upload(); }); // 当有文件被添加进队列的时候 uploader.on('fileQueued', function (file) { serialNumber++; $("#uploadstatutable").append(gethtm(serialNumber, file.name, file.size, file.id)); $("#caozuo" + file.id).click(function () { uploader.removeFile(file.id, true) $("#row" + file.id).remove(); serialNumber--; filequee--; }); uploader.md5File(file).then(function (val) { fileMd5info[uuid + file.id] = val; uploader.upload(file);// 计算完文件的md5之后,直接上传文件 }); filequee++; }); // 文件上传过程中创建进度条实时显示。 uploader.on('uploadProgress', function (file, percentage) { var $li = $('#progress' + file.id); var $litext = $('#progresstext' + file.id); $litext.text('上传中'); $li.text((percentage * 100 - 1).toFixed(2) + '%'); }); // 单个文件上传成功时 uploader.on('uploadSuccess', function (file) { $('#progresstext' + file.id).text('已完成'); $('#progress' + file.id).text("100.00%"); filequee--; }); // 单个文件上传出错时 uploader.on('uploadError', function (file, reason) { $('#progresstext' + file.id).text('上传出错,原因:' + reason); }); uploader.on('uploadBeforeSend', function (block, data) { // 将所有md5数据携带发送过去。 data.fileMd5 = JSON.stringify(fileMd5info); }); // 所有文件上传完成时触发 uploader.on('uploadFinished', function (file) { layer.msg('上传完成'); }); uploader.on("error", function (type) { if (type == "F_DUPLICATE") { alert("请不要重复选择文件!"); } else if (type == "F_EXCEED_SIZE") { alert("附件总大小不可超过" + allMaxSize + "Mb"); } }); }); function assignment() { $(".upfiletable").each(function () { var fileid = $(this).data("id"); var cjsons = $("#chapterJson").val(); var jsonarray; if (cjsons == undefined || cjsons == null || cjsons == '') { jsonarray = []; } else { jsonarray = eval('(' + cjsons + ')'); } var cjson = {}; var zipname = $("#na" + fileid).text(); cjson.name = $("#name" + fileid).val(); cjson.coursenumber = $("#coursenumber" + fileid).val(); cjson.zipname = zipname; cjson.courselen = $("#xs" + fileid).val(); cjson.credit = $("#xf" + fileid).val(); cjson.size = $("#size" + fileid).text(); cjson.sorts = $("#xh" + fileid).text(); cjson.url = uuid + '/' + fileMd5info[uuid + fileid] + zipname.substring(zipname.lastIndexOf(".")); jsonarray.push(cjson); $("#chapterJson").val(JSON.stringify(jsonarray)); }); } function gethtm(serialNumber, filename, filesize, fileid) { var filenamelast = filename.indexOf('.'); var fa = filename.substring(0, filenamelast); var htm = '<tr id="row' + fileid + '" class="upfiletable" data-id="' + fileid + '">' + '<td id="xh' + fileid + '">' + serialNumber + '</td>' + '<td class="upFileName" id="na' + fileid + '">' + filename + '</td>' + '<td><input lay-verify="required" id="name' + fileid + '" value="' + fa + '"/></td>' + '<td><input lay-verify="required" id="coursenumber' + fileid + '" value=""/></td>' + '<td><input lay-verify="required" class="checkdouble" placeholder="学分" id="xf' + fileid + '"></td>' + '<td><input lay-verify="required" type="number" placeholder="学时(分钟)" id="xs' + fileid + '"></td>' + '<td id="size' + fileid + '">' + ((filesize) / (1024 * 1024)).toFixed(2) + 'Mb</td>' + '<td id="progress' + fileid + '">' + 0 + '%</td>' + '<td id="progresstext' + fileid + '">等待上传</td>' + '<td><a href="javascript:;" id="caozuo' + fileid + '">移除</a></td>' + '</tr>' return htm; } // 提交前校验 function check() { if (serialNumber == 0) { layer.msg('课程压缩包信息缺失'); return false; } var b = 0; $(".checkdouble").each(function () { if (isNaN($(this).val())) { b = 1; } }); if (b == 1) { layer.msg('学分填写有误'); return false; } var flag1 = 0; var flag2 = 0; $(".upFileName").each(function () { var name = $(this).text(); var suffix = name.substring(name.lastIndexOf(".")); if (suffix == '.zip' || suffix == '.rar' || suffix == '.ZIP' || suffix == '.RAR') { flag1 = 1; } else { flag2 = 1; } }); if ($("#courseattr").val() == 0 && flag1 == 1) { layer.msg('VIDEO课程请上传视频文件,不能上传压缩文件'); return false; } if ($("#courseattr").val() == 1 && flag2 == 1) { layer.msg('SCORM课程请上传压缩文件,不能上传视频文件'); return false; } if (filequee > 0) { layer.msg('课程资源列表中的文件还未上传完'); return false; } // 向隐藏域添加子课程信息 assignment(); // 向隐藏域添加需要删除的子课程 $("#deloldtid").val(deloldtid.join(",")); return true; }; </script>
后台部分
//文件上传
// 文件上传 @RequestMapping(value = "/fileupload.do") @ResponseBody public void fileupload(HttpServletRequest request) { UpLoadUtils.sliceFileupload(request); }
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.ytinfo.system.config.SystemConfig;
import com.ytinfo.system.model.FConfig;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.List;
import java.util.Set;
/**
* 上传工具类
*
* @author songJian
* @version 2018-3-29
*/
public class UpLoadUtils {
private static final Logger logger = LoggerFactory.getLogger(UpLoadUtils.class);
public static String upload(MultipartFile file, String path) {
String md5 = Utils.getMD5ByFile(file);
path = path + Utils.getPathByMD5(md5) + "/";
if ("1".equals(SystemConfig.getProperty("upload.mode"))) {
return uploadLocal(file, path);
} else {
return uploadFtp(file, path);
}
}
/**
* @param file
* @param path 注意:本路径请以符号 / 开头,符号 / 结尾
* @return
*/
private static String uploadLocal(MultipartFile file, String path) {
if (file != null && !file.isEmpty()) {
try {
String fileSuffix = "." + FilenameUtils.getExtension(file.getOriginalFilename());
String id = Utils.getuuid();
String rootPath = getPath() + "/upload";
String filePath = path + id + fileSuffix;
Utils.hasfolder(rootPath + path);
file.transferTo(new File(rootPath, filePath));
return "/upload" + filePath;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
private static class SaveFtpFile implements Runnable {
private FConfig fConfig;
private String ftpPath;
private String fileName;
private InputStream inputStream;
private String ftpUserName;
private String ftpPassword;
public SaveFtpFile(FConfig fConfig, String ftpPath, String fileName, String ftpUserName, String ftpPassword, InputStream inputStream) {
this.fConfig = fConfig;
this.ftpPath = ftpPath;
this.fileName = fileName;
this.inputStream = inputStream;
this.ftpUserName = ftpUserName;
this.ftpPassword = ftpPassword;
}
@Override
public void run() {
FtpUtil.uploadFile(fConfig.getFtpHost(), ftpUserName, ftpPassword, fConfig.getFtpPort(), ftpPath, fileName, inputStream);
}
}
private static String uploadFtp(MultipartFile file, String path) {
List<FConfig> fConfigs = getFConfig();
return upload(file, path, fConfigs);
}
private static String upload(MultipartFile mFile, String path, List<FConfig> fConfigs) {
String fileSuffix = "." + FilenameUtils.getExtension(mFile.getOriginalFilename());
String id = Utils.getuuid();
String filePath = path + id + fileSuffix;
String fileName = id + fileSuffix;
String domain = SystemConfig.getProperty("spring.ftp.domainName");
String rootPath = SystemConfig.getProperty("spring.ftp.ftpPath");
String nginxPort = SystemConfig.getProperty("spring.ftp.ftpNginxPort");
String ftpUserName = SystemConfig.getProperty("spring.ftp.ftpUserName");
String ftpPassword = SystemConfig.getProperty("spring.ftp.ftpPassword");
try {
InputStream inputStream = mFile.getInputStream();
ByteArrayOutputStream ba = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) > -1) {
ba.write(buffer, 0, len);
}
ba.flush();
String ftpPath = rootPath + path;
for (FConfig config : fConfigs) {
InputStream stream = new ByteArrayInputStream(ba.toByteArray());
new Thread(new SaveFtpFile(config, ftpPath, fileName, ftpUserName, ftpPassword, stream)).start();
}
ba.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return "http://" + domain + ":" + nginxPort + "/" + rootPath + filePath;
}
/**
* 获取static目录
*
* @return 项目路径
*/
public static String getPath() {
File path = null;
try {
if (StringUtils.isNotBlank(SystemConfig.getProperty("upload.path"))) {
path = new File(ResourceUtils.getURL("file:" + SystemConfig.getProperty("upload.path")).getPath());
} else {
logger.error("upload.path信息未正确配置");
return null;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (!path.exists()) path.mkdirs();
logger.debug("uploadPath:" + path.getAbsolutePath());
return path.getAbsolutePath().replaceAll("\\\\", "/");
}
public static List<FConfig> getFConfig() {
List<FConfig> list = Lists.newArrayList();
String[] h = SystemConfig.getProperty("spring.ftp.ftpHost").split(",");
String[] po = SystemConfig.getProperty("spring.ftp.ftpPort").split(",");
for (int i = 0; i < h.length; i++) {
FConfig fConfig = new FConfig();
fConfig.setFtpHost(h[i]);
fConfig.setFtpPort(Integer.parseInt(po[i]));
list.add(fConfig);
}
return list;
}
/**
* 分片文件上传,文件默认存储在temp/uuid文件夹中
*
* @param request
*/
public static void sliceFileupload(HttpServletRequest request) {
MultipartHttpServletRequest mQuest = (MultipartHttpServletRequest) request;
MultipartFile file = mQuest.getFile("file");// 获得上传的文件
String uuid = request.getParameter("uuid");// 上传站点标识,用于区分各站点,以便判断文件合并信息
String pathuuid = UpLoadUtils.getPath() + "/temp/" + uuid + "/";
JSONObject fileMd5 = JSONObject.parseObject(request.getParameter("fileMd5"));// 获取文件md5
String chunkStr = request.getParameter("chunk");
String chunksStr = request.getParameter("chunks");
if (chunkStr == null) {
chunkStr = "0";
}
if (chunksStr == null) {
chunksStr = "1";
}
Integer chunk = Integer.valueOf(chunkStr);// 第几片
Integer chunks = Integer.valueOf(chunksStr);// 一共分了几片
String fileid = request.getParameter("id");// 文件id(文件分片上传的时候,文件id是一样的,同一个站点不会有相同文件id,但是不同站点的id可能会相同)
logger.info("uuid:{},chunk:{},chunks{}", uuid, chunk, chunks);
if (!file.isEmpty()) {
String oldfilename = file.getOriginalFilename();
String suffix = FilenameUtils.getExtension(oldfilename);
try {
Utils.hasfolder(pathuuid);
File uploadFile = new File(pathuuid + chunk + fileid + "." + suffix);
FileCopyUtils.copy(file.getBytes(), uploadFile);
Set<File> files = Sets.newConcurrentHashSet();
for (int i = 0; i < chunks; i++) {
File chunkFile = new File(pathuuid + i + fileid + "." + suffix);
if (chunkFile.exists()) {
files.add(chunkFile);
}
}
if (chunks == files.size()) {// 文件全部到齐,开始合并
String fFileName = fileMd5.getString(uuid + fileid) + "." + FilenameUtils.getExtension(oldfilename);
try {
logger.info("开始合并分片文件,uuid:{},fileid:{},fFileName:{}", uuid, fileid, fFileName);
File destFile = new File(pathuuid + fFileName);
OutputStream out = new FileOutputStream(destFile);
BufferedOutputStream bos = new BufferedOutputStream(out);
for (int i = 0; i < chunks; i++) {// 按顺序,从第一个开始进行拼接(不直接循环files进行拼接,不仅因为hash是无序的,传过来的顺序也是无序的,就算用hashtree存了,也不能使用files)
File srcFile = new File(pathuuid + i + fileid + "." + suffix);
InputStream in = new FileInputStream(srcFile);
BufferedInputStream bis = new BufferedInputStream(in);
byte[] bytes = new byte[1024 * 1024];
int len = -1;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bis.close();
in.close();
srcFile.delete();
}
if (bos != null) bos.close();
if (out != null) out.close();
logger.info("分片文件合并完成,fFileName:{}", fFileName);
} catch (Exception e) {
logger.info("分片文件合并出错,fFileName:{}", fFileName);
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
发布者:songJian 点击数:2399 发布时间:2017-06-17 01:58:05 更新时间:2018-10-13 23:36:45
正在加载评论...