JS-上传多张图片-支持拖动设置顺序-跨域上传

版权声明:本文为博主原创文章,转载注明地址:http://blog.csdn.net/wang704987562 https://blog.csdn.net/wang704987562/article/details/81810061

功能

1.上传多张图片,放弃传统input.file形式上传,自定义数组保存文件;
2.可一次性选择多张图片,可追加图片,图片可以预览;
3.可拖动图片,顺序默认从左0开始,采用jquery-ui实现;
4.可删除单个图片,或清空所有图片;
5.跨域上传;
6.防止按钮重复提交;
7.判断文件类型,过滤非图片文件;

html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>上传多张图片文件,可拖动图片排序</title>
        <!--pomelo-toast-->
        <link rel="stylesheet" href="http://d3.itsaoko.com/template/source/1880821582xN.css">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css" >
        <style>
            .container {
                width: 705px;
                margin: 0 auto;
            }

            .img_wrapper {
                width: 100%;
                min-height: 300px;
                display: flex;
                flex-wrap: wrap;
            }
            .dragWrapper {
                position: relative;
                display: inline-block;
            }
            .btn_wrapper {
                display: flex;
                justify-content: center;
            }
            .btn,.clearBtn {
                margin-right: 50px;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="img_wrapper">

            </div>
            <div class="btn_wrapper">
                <!--不使用file的默认样式,隐藏file选择框,使用button的click事件触发选择文件-->
                <input type="file" name="files" id="files" multiple style="display: none;"  data-name="files1"/>
                <button class="btn">选择文件</button>
                <button class="clearBtn">清空文件</button>
                <button class="uploadBtn">上传文件</button>
            </div>
        </div>

    </body>
    <!--pomelo-toast-->
    <script src="http://d3.itsaoko.com/template/source/18808220295.js"></script>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script
  src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"
  integrity="sha256-T0Vest3yCU7pafRw9r+settMBX6JkKN06dqBnpQ8d30="
  crossorigin="anonymous"></script>

</html>

JS

<script type="text/javascript">
    var toast;
    $(document).ready(function() {
        toast = new PomeloToast();
        //选择文件点击事件
        $(".btn").click(function(e){
            e.preventDefault(); 
            $("#files").trigger("click");
        });
        //保存文件数组
        var imgFiles = [];
        //记录当前文件数
        var fileCount = 0;
        //文件变化事件
        $("#files").change(function() {
            var files = $(this)[0].files;
            var imageType = /^image\//;
            var namePrefix = $(this).data("name");
            for(var i = 0;i < files.length;i ++) {
                var file = files[i];
                var fileType = file.type;
                if(!imageType.test(fileType)) {
                    toast.show("请选择图片类型文件");
                    return;
                }
                var fileName = file.name;
                //文件的唯一标识
                fileCount++;
                var fileId = namePrefix + '_' + fileName + '_' + fileCount;
                //保存文件到数组
                imgFiles.push({
                    id : fileId,
                    file : file
                });
                //预览图片
                var render = new FileReader();
                render.fileId = fileId;
                render.img = $(this);
                render.onload = function (e) {
                //创建img
                var imgHtml = '<div class="dragWrapper" style="">' +
                    '<img src="' + e.target.result + '" width="100" height="100" data-name="' + e.target.fileId + '" />' +
                    '<button class="btn default  removeImg" style="position: absolute;top: 0;right: 0;margin: 0px;">删除</button>' + '</div>';
                    e.target.img.parent().siblings(".img_wrapper").append(imgHtml);
                };
                render.readAsDataURL(files[i]);
            }
            //清空file框文件,可以连续选择同一文件
            $(this).val('');
            //刷新拖动排序
            $(".container").sortable('refresh');
        });
        //删除单个文件,因为动态添加,所以使用代理
        $(".img_wrapper").on("click", ".removeImg", function() {
            var id = $(this).siblings("img").data("name");
             var index = 0;
            //删除文件
            while(index < imgFiles.length) {
                if(imgFiles[index].id == id) {
                    imgFiles.splice(index, 1);
                    break;
                }
                index++;
            }
            $(this).parent().remove();
        });
        //清空文件
        $(".clearBtn").click(function() {
            //清空文件数组
            imgFiles = [];
            $(".img_wrapper").html('');
        });
        //图片拖动排序
        $(".container").sortable({
            items:'.dragWrapper'
        });
        var uploadFinish = true;
        //上传文件
        $(".uploadBtn").click(function() {
            if(imgFiles.length < 1) {
                toast.show("文件为空");
                return;
            }
            if(!uploadFinish) {
                //文件正在上传
                return;
            }
            uploadFinish = false;
            var formData = new FormData();
            //设置文件顺序
            $.each($("div.img_wrapper"), function(index, value) {
                var imgs = $(this).find("img");
                var imgOrder = 1;
                $.each(imgs, function() {
                    $(this).attr("data-order", imgOrder);
                    imgOrder++;
                });
            });
            //设置文件参数 key:name+order value:file
            $.each(imgFiles, function(index, value) {
                var id = value.id;
                //获取该图片对应的顺序
                var order = $("img[data-name='" + id + "']").data("order");
                id = id.substr(0, id.lastIndexOf("_"));
                id = id + "_" + order;
                formData.append(id, value.file);
            });

           $.ajax({
                url: 'http://localhost:8080/test/uploads',
                data: formData,
                type: 'POST',
                cache: false,
                contentType: false,
                processData: false,
                success: function(data){
                    toast.show("上传成功");
                    //清空文件数组
                    imgFiles = [];
                    //清空预览图片
                    $(".img_wrapper").html('');
                },
                error: function(e) {
                    toast.show("上传失败");
                },
                complete: function() {
                    //设置请求完成
                    uploadFinish = true;
                }
            });

        });

    });
</script>

后端使用Spring MVC接收文件

TestController

/**
 * @author wzx
 * @time 2018/8/4
 */
@Controller
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/uploads")
    @ResponseBody
    @CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.OPTIONS},
            allowedHeaders = {"Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"},
            exposedHeaders = {"Access-Control-Allow-Origin", "Access-Control-Allow-Credentials"})
    public String upload(MultipartFile[] files, HttpServletRequest request) {
        System.out.println(files.length);
        Map<String, MultipartFile> fileMap = ((DefaultMultipartHttpServletRequest) request).getFileMap();
        System.out.println("fileMap size:" + fileMap.size());
        fileMap.forEach((k,v)-> System.out.println(k));
        return "ok";
    }
}

两点说明:
1.可以使用MultipartFile[]数组接收,缺点是files只能跟前端的参数名对应;使用DefaultMultipartHttpServletRequest.getFileMap()获取参数名和对应文件,这里可以处理文件的顺序;
2.@CrossOrigin注解处理跨域请求;

效果

这里写图片描述

猜你喜欢

转载自blog.csdn.net/wang704987562/article/details/81810061