electron中拖动文件到桌面案例

效果图

main.js

javascript 复制代码
const path = require('node:path');
const { app, BrowserWindow, ipcMain, nativeImage } = require('electron');

const SAFE_FILES = ['file1.txt'];

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    title: 'File Drag Demo',
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
    },
  });

  win.loadFile('index.html');
}

app.whenReady().then(() => {
  ipcMain.on('get-draggable-files-sync', (event) => {
    event.returnValue = SAFE_FILES.map((name) => ({
      name,
      path: path.resolve(__dirname, name),
    }));
  });

  ipcMain.on('start-file-drag-sync', (event, filePath) => {
    const allowedPaths = new Set(SAFE_FILES.map((name) => path.resolve(__dirname, name)));
    const targetPath = path.resolve(filePath);
    event.returnValue = false;

    if (!allowedPaths.has(targetPath)) {
      return;
    }

    const iconPath = path.join(__dirname, 'drag-icon.png');
    const dragIcon = nativeImage.createFromPath(iconPath);

    if (dragIcon.isEmpty()) {
      console.error(`Failed to decode drag icon: ${iconPath}`);
      return;
    }

    try {
      event.sender.startDrag({
        file: targetPath,
        icon: dragIcon,
      });
      event.returnValue = true;
    } catch (error) {
      console.error('startDrag failed:', error);
    }
  });

  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

preload.js

javascript 复制代码
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('fileDrag', {
  list() {
    return ipcRenderer.sendSync('get-draggable-files-sync');
  },
  start(filePath) {
    return ipcRenderer.sendSync('start-file-drag-sync', filePath);
  },
});

renderer.js

javascript 复制代码
const fileList = document.querySelector('#fileList');
const files = window.fileDrag.list();

for (const fileEntry of files) {
  const item = document.createElement('div');
  item.className = 'file-item';
  item.draggable = true;
  item.textContent = fileEntry.name;

  item.addEventListener('dragstart', (event) => {
    const ok = window.fileDrag.start(fileEntry.path);
    if (!ok) {
      event.preventDefault();
      console.error(`Drag rejected for ${fileEntry.name}`);
    }
  });

  fileList.append(item);
}

index.html

html 复制代码
<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Electron 文件拖拽 Demo</title>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <main class="app">
      <h1>拖文件到桌面</h1>
      <p>按住下面任意文件,直接拖到桌面或文件夹里。</p>

      <section class="file-list" id="fileList"></section>
    </main>

    <script src="./renderer.js"></script>
  </body>
</html>

style.css

css 复制代码
:root {
  color-scheme: light dark;
  font-family: Arial, "Microsoft YaHei", sans-serif;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

.app {
  max-width: 420px;
  margin: 48px auto;
  padding: 0 24px;
}

h1 {
  margin: 0 0 8px;
  font-size: 28px;
}

p {
  margin: 0 0 24px;
  color: #666;
}

.file-list {
  display: grid;
  gap: 12px;
}

.file-item {
  padding: 16px 18px;
  border: 1px solid #d6d6d6;
  border-radius: 12px;
  background: #f7f7f7;
  cursor: grab;
  user-select: none;
}

.file-item:active {
  cursor: grabbing;
}

@media (prefers-color-scheme: dark) {
  body {
    background: #202124;
    color: white;
  }

  p {
    color: #bdbdbd;
  }

  .file-item {
    border-color: #555;
    background: #2b2c2f;
  }
}

@media (prefers-color-scheme: light) {
  body {
    background: #fff;
    color: black;
  }
}
相关推荐
meilindehuzi_a13 小时前
Vue3组件样式隔离与组件通信实战:从 scoped、props 校验到记事本应用
前端·javascript·vue.js
LaughingZhu13 小时前
Product Hunt 每日热榜 | 2026-07-28
前端·神经网络·react.js·搜索引擎·前端框架
imber15 小时前
别把多平台发布当复制粘贴:一套可复用的内容工程工作流
electron
imber18 小时前
Visual Muse 三平台真实发布验收
electron
陈随易20 小时前
在 VSCode 里,把项目一键部署到服务器
前端·后端·程序员
Highcharts.js20 小时前
教程:基于 React + Highcharts 构建一个单页应用程序、按需数据拉取与图表渲染
开发语言·前端·数据结构·react.js·前端框架·highcharts·页面应用
To_OC21 小时前
我被 useState 坑了两次之后,终于把它的脾气摸透了
前端·javascript·react.js
鱼樱前端21 小时前
我用 Claude Code 后,编码效率翻 3 倍。但更值钱的是别的。
前端·后端·ai编程
_lucas21 小时前
给知识库网站接入AI问答
前端·ai编程·全栈
前端糕手1 天前
前端面试题大全:JavaScript + Vue3 + React + TypeScript + 工程化 + 性能优化
前端