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   点击数:2289   发布时间:2017-06-17 01:58:05   更新时间:2018-10-13 23:36:45
正在加载评论...
相关文章