1、参考:
- 使用 JavaScript File API 实现文件上传
- FileReader.readAsDataURL()
- 基于Servlet3的文件上传中的示例2:基于JQuery的单文件上传
2、onpaste 剪贴板事件
onpaste 事件在用户向元素中粘贴文本时触发。有三种方式可以在元素中粘贴内容:
- 按下 CTRL + V
- 从浏览器的编辑菜单中选择 Paste(粘贴)菜单项
- 右击鼠标按钮在上下文菜单中选择 “Paste(粘贴)” 菜单项
粘贴事件提供了一个clipboardData的属性,如果该属性有items属性,那么就可以查看items中是否有图片类型的数据了。
3、clipboardData介绍
clipboardData实际上是一个DataTransfer类型的对象(DataTransfer是拖动产生的一个对象)。clipboardData的属性介绍:
属性 | 类型 | 说明 |
---|---|---|
dropEffect | String | 默认是 none |
effectAllowed | String | 默认是 uninitialized |
files | FileList | 粘贴操作为空List |
items | DataTransferItemList | 剪切板中的各项数据 |
types | Array | 剪切板中的数据类型 |
说明:
- files
文件(例如剪切板中的数据) - items:items是一个DataTransferItemList对象,里面都是DataTransferItem类型的数据。
- items的DataTransferItem有以下两个属性:
属性 | 说明 |
---|---|
kind | 一般为string或者file |
type | 具体的数据类型,例如:哪种类型字符串或者哪种类型的文件,即MIME-Type |
- items的方法
方法 | 参数 | 说明 |
---|---|---|
getAsFile | 空 | 如果kind是file,可以用该方法获取到文件 |
getAsString | 回调函数 | 如果kind是string,可以用该方法获取到字符串,字符串需要用回调函数得到,回调函数的第一个参数就是剪切板中的字符串 |
- types:一般types中常见的值有:
值 | 说明 |
---|---|
text/plain | 普通字符串 |
text/html | 带有样式的html |
4、FileReader对象
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。其中,File对象可以是:
- 来自用户在一个元素上选择文件后返回的FileList对象
- 来自拖放操作生成的 DataTransfer对象
- 来自在一个HTMLCanvasElement上执行mozGetAsFile()方法后返回结果
FileReader对象的事件处理:
- FileReader.onload处理load事件,该事件在读取操作完成时触发。
- FileReader.onloadend处理loadend事件,该事件在读取操作结束时(要么成功,要么失败)触发。
FileReader对象的readAsDataURL()方法:
- FileReader.readAsDataURL()开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容。
- readAsDataURL: 该方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成(DONE),并触发 loadend 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。
5、示例:模拟实现CSDN Markdown编辑器复制图片上传的功能
5.1、环境:Tomcat9、JDK8
5.2、前端页面
```html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en"><head><meta charset="UTF-8"><title>利用JavaScript从剪贴板获取图片并发送</title><script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script><script type="text/javascript">$(function () {document.getElementById("blog").addEventListener('paste', function (e) {var items;if (e.clipboardData && e.clipboardData.items) {items = e.clipboardData.items;if (items) {items = Array.prototype.filter.call(items, function (element) {return element.type.indexOf("image") >= 0;});Array.prototype.forEach.call(items, function (item) {var blob = item.getAsFile();var reader = new FileReader();reader.onloadend = function (event) {var imgBase64 = event.target.result;console.log(imgBase64); // base64var dataURI = imgBase64;var blob = dataURItoBlob(dataURI); // blobconsole.log(blob);uploadImg(blob);};reader.readAsDataURL(blob);});}}});});// base64 to blob二进制function dataURItoBlob(dataURI) {var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; // mime类型var byteString = atob(dataURI.split(',')[1]); //base64 解码var arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组var intArray = new Uint8Array(arrayBuffer); //创建视图for (var i = 0; i < byteString.length; i++) {intArray[i] = byteString.charCodeAt(i);}return new Blob([intArray], {type: mimeString});}//上传图片function uploadImg(file) {var formData = new FormData();formData.append('imageFile', file);formData.append('info', 'haha'); // 添加自定义数据$.ajax({data:formData,method:'POST',// 告诉jQuery不要去处理发送的数据processData: false,contentType: false,url:'${pageContext.request.contextPath}/clipboardImgUpload',success:function (data) {var data = JSON.parse(data);var tarBox = document.getElementById('box');if (data.code == 1) {document.getElementById("blog").value = data.src;var img = document.createElement('img');img.src = data.src;tarBox.appendChild(img);} else {alert(data.msg);}},error:function (data) {console.log(data);}})}</script></head><body style="padding: 0 7% 0 7%;"><textarea style="width: 49%;height: 600px;" id="blog"></textarea><span id="box" style="border:1px solid darkblue; float: right;width: 50%;height: 600px;"></span></body>
</html>
```
5.3、后台代码
```java
@MultipartConfig //标识Servlet支持文件上传
@WebServlet(urlPatterns = "/clipboardImgUpload")
public class ClipboardImgUploadServlet extends HttpServlet {@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");String savePath = request.getServletContext().getRealPath("\\uploadFile"); //存储路径File path = new File(savePath);if (!path.exists()) {path.mkdirs();}PrintWriter out = response.getWriter();String res = "";try {System.out.println(request.getParameter("info"));Part part = request.getPart("imageFile"); //通过表单file控件(<input type="file" name="file">)的名字直接获取Part对象String fileName = UUID.randomUUID().toString() + ".png";part.write(savePath + File.separator + fileName); //把文件写到指定路径res = "{\"code\":1,\"msg\":\"图片上传成功\",\"src\":\"uploadFile/" + fileName + "\"}";} catch (IOException | ServletException e) {e.printStackTrace();res = "{\"code\":0,\"msg\":\"图片上传失败\",\"src\":\"\"}";} finally {System.out.println(res);out.println(res);out.flush();out.close();}}}
```
- 运行程序:
默认页面
复制一张图片,直接在左边的textarea中按快捷键ctrl+v,效果如下图