原生文件拖 & 放

概览

作为桌面程序,当然希望能够实现操作系统的 drag & drop 功能。 很多网站已经支持拖拽文件, Electron 当然也支持

要在您的应用中实现此功能,您需要调用 webContent.startDrag(item) API 响应 ondragstart 事件。

示例

一个演示如何动态创建要从窗口中拖出的文件的示例。

Preload.js

preload.js 中使用 contextBridge 注入方法 window.electron.startDrag(...) 将向主进程发送IPC消息。

  1. const { contextBridge, ipcRenderer } = require('electron')
  2. const path = require('node:path')
  3. contextBridge.exposeInMainWorld('electron', {
  4. startDrag: (fileName) => {
  5. ipcRenderer.send('ondragstart', path.join(process.cwd(), fileName))
  6. }
  7. })

Index.html

添加一个可拖动元素到 index.html, 并引用你的渲染器脚本:

  1. <div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag">拖动我</div>
  2. <script src="renderer.js"></script>

Renderer.js

renderer.js 通过调用通过上述 contextBridge 添加的方法来设置渲染器进程处理拖动事件。

  1. document.getElementById('drag').ondragstart = (event) => {
  2. event.preventDefault()
  3. window.electron.startDrag('drag-and-drop.md')
  4. }

Main.js

在主进程中(main.js 文件),将收到的事件带上文件路径和图标扩展到正在拖动的文件:

docs/fiddles/features/drag-and-drop (27.0.1)Open in Fiddle

  • main.js
  • preload.js
  • index.html
  • renderer.js
  1. const { app, BrowserWindow, ipcMain } = require('electron')
  2. const path = require('node:path')
  3. const fs = require('node:fs')
  4. const https = require('node:https')
  5. function createWindow () {
  6. const win = new BrowserWindow({
  7. width: 800,
  8. height: 600,
  9. webPreferences: {
  10. preload: path.join(__dirname, 'preload.js')
  11. }
  12. })
  13. win.loadFile('index.html')
  14. }
  15. const iconName = path.join(__dirname, 'iconForDragAndDrop.png')
  16. const icon = fs.createWriteStream(iconName)
  17. // Create a new file to copy - you can also copy existing files.
  18. fs.writeFileSync(path.join(__dirname, 'drag-and-drop-1.md'), '# First file to test drag and drop')
  19. fs.writeFileSync(path.join(__dirname, 'drag-and-drop-2.md'), '# Second file to test drag and drop')
  20. https.get('https://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
  21. response.pipe(icon)
  22. })
  23. app.whenReady().then(createWindow)
  24. ipcMain.on('ondragstart', (event, filePath) => {
  25. event.sender.startDrag({
  26. file: path.join(__dirname, filePath),
  27. icon: iconName
  28. })
  29. })
  30. app.on('window-all-closed', () => {
  31. if (process.platform !== 'darwin') {
  32. app.quit()
  33. }
  34. })
  35. app.on('activate', () => {
  36. if (BrowserWindow.getAllWindows().length === 0) {
  37. createWindow()
  38. }
  39. })
  1. const { contextBridge, ipcRenderer } = require('electron')
  2. contextBridge.exposeInMainWorld('electron', {
  3. startDrag: (fileName) => {
  4. ipcRenderer.send('ondragstart', fileName)
  5. }
  6. })
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Hello World!</title>
  6. <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
  7. </head>
  8. <body>
  9. <h1>Hello World!</h1>
  10. <p>Drag the boxes below to somewhere in your OS (Finder/Explorer, Desktop, etc.) to copy an example markdown file.</p>
  11. <div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag1">Drag me - File 1</div>
  12. <div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag2">Drag me - File 2</div>
  13. <script src="renderer.js"></script>
  14. </body>
  15. </html>
  1. document.getElementById('drag1').ondragstart = (event) => {
  2. event.preventDefault()
  3. window.electron.startDrag('drag-and-drop-1.md')
  4. }
  5. document.getElementById('drag2').ondragstart = (event) => {
  6. event.preventDefault()
  7. window.electron.startDrag('drag-and-drop-2.md')
  8. }

启动 Electron 应用程序后,尝试将该项从 BrowserWindow 拖放到桌面上。 在本指南中,本项是位于项目根目录下的 Markdown 文件:

拖放