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;
  }
}
相关推荐
JavaGuide2 小时前
NVIDIA 又开源了!这次给 AI Agent 加上权限管控
前端·后端
excel2 小时前
prisma 如何处理数据库竞态
前端·数据库·后端
莪_幻尘4 小时前
Skill 体检:30 个 Skill 全凭感觉?体检器先自曝了 8 个“假 0 分
前端·人工智能·llm
风骏时光牛马4 小时前
AI模型综合能力评测:性能、指令遵循与多场景实测对比
前端
Frag0ut4 小时前
Chrome与Chromium内核浏览器在Windows 11上的新特性全景解析
前端·chrome·windows·web安全·chromium·gemini ai·playready drm
hiahiahia1234 小时前
实现完整 Tool Dispatcher
开发语言·前端
IT_陈寒5 小时前
Java线程池这破玩意,差点让我周末加班排查到凌晨
前端·人工智能·后端
Mr_Mao5 小时前
告别选型困难!集 VueUse、ahooks、Mantine 于一身:286 个 Hook 的 ReaUse 来了
前端·javascript·react.js
泡海椒6 小时前
趋势分析报表:jquick-pdf折线图PDF生成实战
java·大数据·运维·服务器·前端·pdf
默_笙6 小时前
🚙 一条腿走路会摔:ES 关键词检索、混合召回与 ReRank 裁判
前端·javascript