Electron桌面端拖拽下载的实现
Electron桌面端拖拽下载的实现
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就可以实现了, 具体就不多说了,如果有问题,欢迎留言讨论。