图片上传的三种方式(拖拽|粘贴|点击)

/ 前端Java / 1 条评论 / 4205浏览

目标效果

拖拽、粘贴、点击 三种方式集成在一个图片上传插件。如下图效果

效果图

Html前端

Html代码

<html>
<head>
    <title>图片上传</title>
    <style type="text/css">
        /* 自定义图像上传样式 */
         #markdown_upload_image_panel {
            width: 100%;
            height: 100px;
            line-height: 100px;
            text-align: center;
            background-color: #e6dce1;
            border-color: black;
            border-style: dashed;
            border-width: thin;
        }
        #imgageFile {
            position:relative;
            top:-100px;
            left:0px;
            height:100%;
            width:100%;
            opacity:0;
        }
        .md-prompt-dialog {
            width: 500px;
            border: black;
            border-style: ridge;
            border-width: 1px;
            padding: 15px;
        }
        .md-prompt-dialog button {
            float:right;
        }
    </style>
</head>
<body>
<div class="md-prompt-dialog">
    <div>
        <p> <b>插入图片</b>
        </p>
        <p>1.点击下方区域,完成上传</p>
        <p>2.当前状态粘贴图片,完成上传</p>
        <p>3.图片拖拽到下方区域,完成上传</p>
        <p></p>
        <div id="markdown_upload_image_panel">
            <span id="markdown_upload_image_trip_span">拖拽图片 | 粘贴图片 | 点击上传</span>
            <input type="file" id="imgageFile">
        </div>
        <p></p>
        <br>
        <p>请在下方的输入框内输入要插入的远程图片地址</p>
    </div>
    <form>
        <input type="text">
        <button type="button" class="btn-s primary">确定</button>
        <button type="button" class="btn-s">取消</button>
    </form>
</div>
</body>
</html>

拖拽上传

            //拖拽上传图片
            var uploadTripSpan = document.getElementById('markdown_upload_image_trip_span');
            //注册事件
            uploadBox.ondragover=function (e){
                e.preventDefault();
            }
            uploadBox.ondrop=function (e){
                e.preventDefault();
                var f=e.dataTransfer.files[0];//获取到第一个上传的文件对象
                var fr=new FileReader();//实例FileReader对象
                fr.readAsDataURL(f);//把上传的文件对象转换成url
                fr.onload=function (e){
                    //var imageData = e.target.result;  //上传文件的URL
                    var imageData = this.result;    //base64图片
                    uploadTripSpan.innerText = "图片上传中..."
                        
                    //上传图片(这里使用了tale框架),直接改为$.ajax提交数据即可
                    tale.post({
                        url:'/admin/attach/upload/buffer',
                        data:{image:imageData},
                        success: function (result) {
                            if (result && result.success) {
                                $("#markdown_upload_image_panel").parent().next().children('input').val(result.payload);
                                uploadTripSpan.innerText = "上传完成!";
                            } else {
                                tale.alertError(result.msg || '上传失败,请重试!');
                            }
                        }
                    });
                }
            };

粘贴上传

            //粘贴图片
            var uploadTripSpan = document.getElementById('markdown_upload_image_trip_span');
            document.addEventListener('paste', function (event) {
                var items = (event.clipboardData || window.clipboardData).items;
                var file = null;
                if (items && items.length) {
                    // 搜索剪切板items
                    for (var i = 0; i < items.length; i++) {
                        if (items[i].type.indexOf('image') !== -1) {
                            file = items[i].getAsFile();
                            break;
                        }
                    }
                }
                if(!file)return;
                // 此时file就是我们的剪切板中的图片对象
                var reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = function(event){
                    var imageData = event.target.result;
                    uploadTripSpan.innerText = "图片上传中..."
                    ///上传图片(这里使用了tale框架),直接改为$.ajax提交数据即可
                    tale.post({
                        url:'/admin/attach/upload/buffer',
                        data:{image:imageData},
                        success: function (result) {
                            if (result && result.success) {
                                $("#markdown_upload_image_panel").parent().next().children('input').val(result.payload);
                                uploadTripSpan.innerText = "上传完成!";
                            } else {
                                tale.alertError(result.msg || '上传失败,请重试!');
                            }
                        }
                    });
                }
            });

点击上传

            //点击上传
            var uploadTripSpan = document.getElementById('markdown_upload_image_trip_span');
            $("body").delegate('#imgageFile', 'change',function(){
                var fd = new FormData();
                fd.append("file", $("#imgageFile").get(0).files[0]);
                $.ajax({
                    url: '/admin/attach/upload',
                    type: "POST",
                    processData: false,
                    contentType: false,
                    data: fd,
                    success: function(result) {
                        if (result && result.success) {
                            $("#markdown_upload_image_panel").parent().next().children('input').val(result.payload);
                            uploadTripSpan.innerText = "上传完成!";
                        } else {
                            tale.alertError(result.msg || '上传失败,请重试!');
                        }
                    }
                });
            });

注意事项

1.拖拽、粘贴 是使用base64方式上传、点击直接以file形式上传

2.点击上传的事件绑定方式

推荐方式

$("body").delegate('#imgageFile', 'change',function(){
    //处理业务
});

不推荐方式

$('#imgageFile').on('change',function(){
    //处理业务
});

推荐理由

a.即使 #imgageFile标签, 是页面加载完后才插入的,事件也可绑定成功

b.上传过程把file插入new FormData(), 使用该方式可以避免change事件仅触发一次的问题

3.如果页面加载完后,才载入.md-prompt-dialog标签块,可以使用定时器检测

    //使用定时器检测是否已加载图像上传面板
    var uploadInterval= window.setInterval(uploadClock,500)
    function uploadClock()
    {
        //实现图片拖拽、粘贴上传
        var uploadBox = document.getElementById('markdown_upload_image_panel');
        if(uploadBox){
            //停止定时器
            window.clearInterval(uploadInterval);

            //处理业务...
        }
    }

Java后端

Base64服务端接口

/**
     * 字符串格式上传文件接口
     *
     * @param request
     * @return
     */
    @ResponseBody
    @PostMapping(value = "upload/buffer")
    @Transactional(rollbackFor = TipException.class)
    public RestResponseBo uploadbuffer(HttpServletRequest request, @RequestParam String image) throws IOException {
        try {
        	if(image==null)return RestResponseBo.fail("上传图片读取错误,请重试!");
        	String[] imageInfo = image.split(",");
        	String imageHeader = imageInfo[0];
        	BufferedImage bufferImage = ImageUtil.decodeToImage(imageInfo[1]);
            UserVo users = this.user(request);
            Integer uid = users.getUid();
            //data:image/jpeg;base64
            String ftype = imageHeader.split("/")[1].split(";")[0];
            String fname = "blog-"+UUID.randomUUID().toString()+"."+ftype;

            String fkey = TaleUtils.getFileKey(fname);
            File file = new File(CLASSPATH+fkey);
            try {
            	//添加水印
            	//bufferImage = ImageUtil.imageDrawText(bufferImage, DRAWTEXT);
            	//保存图片
            	FileOutputStream out = new FileOutputStream(file);
                ImageIO.write(bufferImage, ftype, out);
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            attachService.save(fname, fkey, Types.IMAGE.getType(), uid);
            
            return RestResponseBo.ok(fkey);

        } catch (Exception e) {
            return RestResponseBo.fail();
        }
        
    }

File服务端接口

/**
     * 上传文件接口
     *
     * @param request
     * @return
     */
    @PostMapping(value = "upload")
    @ResponseBody
    @Transactional(rollbackFor = TipException.class)
    public RestResponseBo upload(HttpServletRequest request, @RequestParam("file") MultipartFile[] multipartFiles) throws IOException {
        UserVo users = this.user(request);
        Integer uid = users.getUid();
        List<String> errorFiles = new ArrayList<>();
        try {
            for (MultipartFile multipartFile : multipartFiles) {
                String fname = multipartFile.getOriginalFilename();
                if (multipartFile.getSize() <= WebConst.MAX_FILE_SIZE) {
                    String fkey = TaleUtils.getFileKey(fname);
                    String ftype = TaleUtils.isImage(multipartFile.getInputStream()) ? Types.IMAGE.getType() : Types.FILE.getType();
                    File file = new File(CLASSPATH+fkey);
                    try {
                    	//从流中读取图片
                    	BufferedImage bufferImage = ImageIO.read(multipartFile.getInputStream());
                    	multipartFile.getInputStream().close();
                    	//添加水印
                    	//bufferImage = ImageUtil.imageDrawText(bufferImage, DRAWTEXT);
                    	//保存图片
                    	FileOutputStream out = new FileOutputStream(file);
                    	String [] filenames = multipartFile.getOriginalFilename().split("\\.");
                    	String fileSuffix = filenames[filenames.length-1];
                        ImageIO.write(bufferImage, fileSuffix, out);
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    attachService.save(fname, fkey, ftype, uid);
                    
                    if(multipartFiles.length==1){
                    	return RestResponseBo.ok(fkey);
                    }
                } else {
                    errorFiles.add(fname);
                }
            }
        } catch (Exception e) {
            return RestResponseBo.fail();
        }
        return RestResponseBo.ok(errorFiles);
    }