首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

如何像掘金编辑器一样粘贴图片即可上传服务器

  • 25-04-20 18:41
  • 4074
  • 6365
juejin.cn

以前写了一篇文章 《前端粘贴复制还能这样玩》,其中涉及到DataTransfer,下面我们来了解一下DataTransfer对象。

DataTransfer对象存在哪些事件对象中

目前就发现拖拽相关事件和paste事件的事件对象中包含DataTransfer对象。 image.png

image.png

DataTransfer对象介绍

在mdn中介绍DataTransfer对象用于保存拖动并放下(drag and drop)过程中的数据。但是paste事件对象中clipboardData也是一个DataTransfer。

  • dropEffect 获取当前选定的拖放操作类型或者设置的为一个新的类型。值必须为 none(项目可能禁止拖放), copy(在新位置生成源项的副本), link(在新位置建立源项目的链接) 或 move(将项目移动到新位置)。它设置的属性表示鼠标拖动的视觉效果,所以我们可以在dragover, dragenter中进行设置该值。
  • effectAllowed 设置源元素(被拖动的元素)允许的拖动效果。none (此项表示不允许放下)、copy (源项目的复制项可能会出现在新位置。)、copyLink (允许 copy 或者 link 操作。)、copyMove (允许 copy 或者 move 操作。)、link (可以在新地方建立与源的链接。)、linkMove (允许 link 或者 move 操作。)、move (一个项目可能被移动到新位置。)、all (允许所有的操作。)、uninitialized (效果没有设置时的默认值,则等同于 all。) 设置对应的属性有对应的效果。即可以限制我们拖动的结果。所以一般在dragstart中进行设置。

effectAllowed和dropEffect相互影响。二者的值需要设置交集。否则拖动是没有效果的。 想要查看效果可以看mdn demo

  • files 获取拖动和粘贴的文件(File)对象列表。这里的文件数据也会保存到items中,以DataTransferItem对象形式存在。
  • items 拖动和粘贴所产生的数据(DataTransferItem)集合。内部包含kind, type两个属性。
  • types 拖动和粘贴所产生的数据的类型。例如文本(text/plain), 图片,文件资源(Files)
  • setData(type, value) 设置拖动所需要的数据源,会加入到items属性集合中。注意设置相同类型type的数据会覆盖。

image.png

image.png

  • getData(type) 通过指定的type获取对应的数据源。
  • clearData(type) 清除指定type的数据源,如果不指定type则清空所有数据,该方法只有在dragstart事件中使用有效。
  • setDragImage(imgElement, xOffset, yOffset) 修改拖动时的图像,一般没啥用,除非你用到了。

DataTransferItem(DataTransfer.items每一项)对象介绍

最主要的是我们应该关注items中的数据对象,即DataTransferItemList对象,它内部包含着粘贴和拖拽的DataTransferItem对象。

我们来看下DataTransferItem对象中属性和方法

  • kind 拖拽或者粘贴项的种类,string 或是 file。
  • type 拖拽或者粘贴项的类型,一般是一个 MIME 类型。

image.png

image.png

  • getAsFile() 如果DataTransferItem是一个文件,那 DataTransferItem.getAsFile()  方法将返回拖拽或者粘贴项数据的File对象。如果拖拽项的数据不是一个文件,则返回 null。

image.png

  • getAsFileSystemHandle() 返回一个Promise, 可以用于判断当前粘贴和拖拽本地磁盘资源项是文件(FileSystemFileHandle)还是文件夹(FileSystemDirectoryHandle)。相比较直接通过kind, type可以更具体的参看类型。

image.png

image.png

如果是文件可以调用getFile()方法获取文件对象。如果是文件夹可以调用getFileHandle(),返回指定名称的FileSystemFileHandle对象然后再进行处理。

  • getAsString(callback) 如果 DataTransferItem 是一个字符串,可以在回调中获取粘贴或者拖拽的字符串的值。如果是文件资源那么回调将不会执行。

image.png

image.png

粘贴的测试代码

js
代码解读
复制代码
"true"> 我是可输入文本的div
<script> const div = document.getElementsByTagName("div")[0] // 这个事件只作用于可编辑的dom元素上。 // 如果元素都没有设置contenteditable="true",那么将作用于整个网页。 div.addEventListener("paste", async function (e) { console.log("粘贴", e.clipboardData.items[0]) // console.log("查看当前粘贴本地的内容是文件还是文件夹", await e.clipboardData.items[0].getAsFileSystemHandle()) // e.clipboardData.items[0].getAsString((res => { // console.log("获取粘贴的字符串值", res) // })) // console.log("粘贴文件返回文件对象", e.clipboardData.items[0].getAsFile()) const fileOrDir = await e.clipboardData.items[0].getAsFileSystemHandle() if(fileOrDir.kind === "file") { console.log("获取文件对象", await fileOrDir.getFile()) } }) script>

拖拽的测试代码

js
代码解读
复制代码
"img-container">
<img id="img" src="https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" alt="" draggable="true" width="100"> <script> /** * * - dragstart`: 开始拖拽对象时触发。在这里开始传递一些源数据。`e.dataTransfer.setData()` * - `dragover`: 当被拖拽元素**未离开**可释放目标元素上时,触发该事件。**在拖拽的过程中。** - `dragleave`: 当被拖拽元素**离开**可释放目标元素上时,触发该事件。 - `drop`: 拖拽元素拖拽到可释放目标对象释放后触发。即在这边获取拖拽元素时传入的一些源数据,做一些其他的逻辑处理。通过`e.dataTransfer.getData()`来获取对应的属性。 * **/ const target = document.getElementById("img-container") const source = document.getElementById("img") source.ondragstart = function(e) { console.log("开始") e.dataTransfer.setData('text/html', "覆盖拖动时产生的text/html类型数据"); e.dataTransfer.setData('text/plain', 'plain text'); // 发送数据 e.dataTransfer.setData('imgName', "test") e.dataTransfer.setData('imgType', "png") e.dataTransfer.setData('imgPath', e.target.currentSrc) e.dataTransfer.clearData() } // target.ondragenter = function(e) { // console.log("e", e) // } // 进入目标元素时触发 target.addEventListener("dragover", (event) => { console.log("进入目标元素移动时触发") // prevent default to allow drop event.preventDefault(); }); // 在使用drop事件之前,需要注册dragover事件。并且需要阻止默认事件。 target.ondrop = async function(e) { console.log("拖拽", e.dataTransfer.items, e.dataTransfer.items[0], e.dataTransfer.items[1], e.dataTransfer.items[2], e.dataTransfer.items[3], e.dataTransfer.items[4]) console.log("查看当前拖拽本地的内容是文件还是文件夹", await e.dataTransfer.items[0].getAsFileSystemHandle()) e.dataTransfer.items[0].getAsString((res => { console.log("获取拖拽的字符串值0", res) })) e.dataTransfer.items[1].getAsString((res => { console.log("获取拖拽的字符串值1", res) })) e.dataTransfer.items[2].getAsString((res => { console.log("获取拖拽的字符串值2", res) })) e.dataTransfer.items[3].getAsString((res => { console.log("获取拖拽的字符串值2", res) })) console.log("拖拽数据中的文件", e.dataTransfer.files, e.dataTransfer.files[0]) console.log("拖拽文件返回文件对象", e.dataTransfer.items[0].getAsFile()) console.log("通过getData(type)获取数据源", e.dataTransfer.getData('text/html')) // console.log("e", e, e.dataTransfer.files[0], e.dataTransfer.items[0], e.dataTransfer.types[0]) // // 在可拖拽的区域拖拽到指定的对象时触发 // const imgName = e.dataTransfer.getData('imgName') // const imgType = e.dataTransfer.getData('imgType') // const imgPath = e.dataTransfer.getData('imgPath') // // 我们拖动文件到别的文件夹时,只是将文件对象加入到目的文件列表中。 // const img = document.createElement("img") // img.setAttribute("src", imgPath) // img.setAttribute("name", imgName) // target.appendChild(img) // img.style.width = "100px" // img.style.height = "100px" // document.body.removeChild(source) } script>

了解上面的这些操作我们就很容易的拿到文件对象上传给服务器了。

html
代码解读
复制代码
// index.html <div contenteditable="true"> 我是可输入文本的div div> <script> const div = document.getElementsByTagName("div")[0] div.addEventListener("paste", async function (e) { console.log("粘贴", e.clipboardData.items[0], e.clipboardData.files[0]) const formData = new FormData() formData.append("file", e.clipboardData.files[0]) let config = { headers: {'Content-Type': 'multipart/form-data'} } axios.post("http://127.0.0.1:3000/login/file", formData, config).then(res => { console.log("res",res) }) }) script>

后端我们是通过nestjs进行处理文件上传的。这里需要配合multer库去实现。

js
代码解读
复制代码
@Post('file') @UseInterceptors( AnyFilesInterceptor({ storage: diskStorage({ destination: 'uploads', filename: (req, file, cb) => { const randomName = Array(32) .fill(null) .map(() => Math.round(Math.random() * 16).toString(16)) .join(''); return cb(null, `${randomName}${extname(file.originalname)}`); }, }), }), ) uploadCopyImgs(@UploadedFiles() files: any) { console.log(files); return `文件上传成功文件名为: ${files[0].filename}`; }

复制上传.gif

往期年度总结

  • 四年沿海城市,刚毕业,一年3家公司
  • 七月仿佛又回到了那一年(2023年中总结)
  • 一位初入职场前端仔的年度终结 <回顾2022,展望2023>
  • 大学两年半的前端学习

往期文章

  • Nest装饰器全解析
  • Nest世界中的AOP
  • Nestjs如何解析http传输的数据
  • 如何理解js的DOM事件系统
  • 半年没看vue官网,3.5刚刚发布,趁机整理下
  • 啊,你还在找一款强大的表格组件吗?
  • 前端大量数据层级展示及搜索定位预览
  • 如何从0开始认识m3u8(提取,解析及下载)
  • 展示大量数据节点(tree),引发的一次性能排查
  • ts装饰器的那点东西
  • 这是你所知道的ts类型断言和类型守卫吗?
  • TypeScript官网内容解读
  • 经常使用ts的你,知道这些内容?
  • 你有了解过原生css的scope?
  • 现在比较常用的移动端调试你知道哪些?
  • 众多跨标签页通信方式,你知道哪些?(二)
  • 众多跨标签页通信方式,你知道哪些?
  • 反调试吗?如何监听devtools的打开与关闭
  • 因为原生,选择一家公司(前端如何防笔试作弊)
  • 结合开发,带你熟悉package.json与tsconfig.json配置
  • 如何优雅的在项目中使用echarts
  • 如何优雅的做项目国际化
  • 近三个月的排错,原来的憧憬消失喽
  • 带你从0开始了解vue3核心(运行时)
  • 带你从0开始了解vue3核心(computed, watch)
  • 带你从0开始了解vue3核心(响应式)
  • 3w+字的后台管理通用功能解决方案送给你
  • 入职之前,狂补技术,4w字的前端技术解决方案送给你(vue3 + vite )

专栏文章

  • 重学vue及其生态
  • 前端面试
  • 前端工程化
  • amis 低代码实战
  • 协议与安全
  • 重学react
  • 重学nodejs
  • 工作总结

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,    支持一下博主~

公众号:全栈追逐者,不定期的更新内容,关注不错过哦!

注:本文转载自juejin.cn的Spirited_Away的文章"https://juejin.cn/post/7433786904678023220"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top