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就可以实现了, 具体就不多说了,如果有问题,欢迎留言讨论。