Electron拖拽下载能力
- 2020 年 1 月 1 日
- 笔记
1. h5 dragDrop简单介绍
dragdrop 是H5标准的新特性之一,针对每个HTML元素,可以设置一个draggable属性,true表示这个元素能够拖拽,false反之。对于能拖拽的元素,其能够响应[‘dragstart’,‘dragover’,‘dragenter’,‘dragleave’,‘dragend’]事件,通过addEventListener可以获取相应的拖拽操作。每个事件提供event参数,在dragdrop场景下,多了dataTransfer属性,dataTransfer包含了拖拽相关的数据信息,例如:
dragEffect: ['copy','move','link','none'], 表示dropEffect将被初始化成期望的动作 effectAllowed:['copy','copymove',....] , 用来指定拖动时被允许的效果 files,拖拽包含的文件列表,如果不涉及文件,那么这个列表为空 setDragImage(imgElement,x,y), 设置拖拽时的图片 setData(type,data), 设置拖拽时的数据信息,type是MIME字符串,例如text/plain getData(type), 返回对应类型的数据信息
2. 拖拽下载的实现
拖拽下载的难点在于:从web页面拖拽出去后,无法感知拖拽的目标地址,因此无法实现下载。因此拖拽下载的问题可以简化为如何感知drop的目标路径。
Electron中使用的内核是Chrome,而chrome在DragDrop setData(dataTransfer 属性之一) 新增了 DownloadURL类型,其作用是将一个已知类型的元素(如图片,octet-stream等拖拽到desktop指定位置)
Chrome: dataTransfer.setData('DownloadURL',[mime]:[filename]:[uri])
我们则可以利用这个特性,拖拽行为产生时,我们通过setData在本地创建一个文件,然后通过electron 调用native模块来监控本地文件的创建,只要能监控到本地文件的创建,那么我们就可以实现下载。
直接贴一下native监控的部分代码吧(windows平台,mac平台有类似的实现),如果不考虑性能问题,在github上也有开源的跨平台库可以使用:
//开始一个监控 m_ulNotifyId = SHChangeNotifyRegister( m_hWnd, SHCNRF_ShellLevel | SHCNRF_NewDelivery, SHCNE_CREATE, WM_USERDEF_FILECHANGED, //自定义消息 1, &shEntry ); //在window消息循环中,处理自定义事件 HRESULT OnShellFileChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled) { //if not file create if (SHCNE_CREATE != lEvent) { return E_FAIL; } //通过SHChangeNotification_Lock 拿到pidl对象 todo... //从PIDL对象中获取targetpath todo... //获取文件名,检测是否是我们已经创建的文件,创建的文件名,可以由electron传递进来(一般为guid形式) //消息重复检测,不要重复回调到了electron render进程 //targetPath 回调 Callback(targetPath); return S_OK; }
至此,electron APP 拖拽下载基本就实现了,基本可以满足所有Electron APP 拖拽下载的场景。
如果需要实现移动或者拖拽上传,只需要处理h5 dragdrop自身的event就可以实现了, 具体就不多说了,如果有问题,欢迎留言讨论。