Electron实现文件复制到剪切板的方案

 更新时间:2024年11月13日 08:23:23   作者:smallzip  
这篇文章主要介绍了Electron实现文件复制到剪切板的解决方案,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下

前言

electron的剪切板没有提供文件、音频、视频等等类型的支持。

技术调研

我们在mac、windows系统中,右键本地文件是支持复制的,并写入到剪切板的速度很快。

基于这个方向,我们查找到了如下方法:

window:使用powershell脚本命令,可以实现文件复制

`powershell -command "& {Set-Clipboard -Path '${filePath}'}"`

mac:使用osascript脚本指令,可以实现文件复制

`osascript -e 'set the clipboard to POSIX file "${filePath}"'`

注意点

powershell和asascript在两个平台支持复制文件、音频、视频等等,前提条件都是需要文件已经存在于本地。

所以,我们复制的内容必须先现在到本地,再进行复制到剪切板。

实现方案

渲染层提供preload

contextBridge.exposeInMainWorld("mainWindowAPI", {
  copyFile: (filePath:string) => ipcRenderer.invoke('copy-file', filePath)
});

复制的实际,需要传递已经缓存到本地的文件路径;

主进程接收ipc

  // 复制文件到剪切板
  ipcMain.on("copy-file", (event: Electron.IpcMainEvent, filePath: string) => {
    // 检查filePath是否存在,不存在则退出
    if(!filePath) {
      event.reply("copy-file", false);
      return;
    }
    
    // 处理base64
    if (filePath.startsWith('data:')) {
      try {
        const image = Buffer.isBuffer(filePath) ? nativeImage.createFromBuffer(filePath) : nativeImage.createFromDataURL(url);
        clipboard.writeImage(image)
        Logger.log(`【copy-file】复制base64成功`)
        event.reply("copy-file", true);
      } catch (error) {
        Logger.log(`【copy-file】复制base64失败 ${error}`)
        event.reply("copy-file", false);
      }
      return
    }

    // 检查是否为本地路径,如果不是本地路径则退出
    if(filePath.includes('file://')) {
      event.reply("copy-file", false);
      return;
    }

    // 执行复制操作
    copyFile(filePath.replace("file:///", "")).then((res: boolean) => {
      event.reply("copy-file", res);
    }).catch(() => {
      event.reply("copy-file", false);
    })
  });

1.检查filePath是否存在,不存在则退出

2.如果是base64图片,则使用electron的nativeImage转换成为PNG图片(或者jpg等,可以看官网

3.检查是否为本地路径,如果不是本地路径则退出,因为复制到剪切板必须是本地文件,网络连接是不支持的

4.是本地连接,去除file:///头,只需要后面的文件路径,路径如下:/Users/自己设备的账户名/Library/Application Support/应用名称/Cache/test.dmg

检查不同平台

/**
 * 复制文件到剪贴板
 *
 * @param localFileUrl 本地文件URL
 * @returns 复制结果,成功为true,失败为false
 */
export function copyFile(localFileUrl: string) {
	if (process.platform === 'darwin') {
		return copyFileForMac(localFileUrl);
	} else if (process.platform === 'win32') {
		return copyFileForWindows(localFileUrl)
	}
}

mac系统复制到剪切板

/**
 * 将文件复制到Mac的剪贴板
 *
 * @param localFileUrl 本地文件的URL路径
 * @returns 返回一个Promise,成功时返回true,失败时返回错误消息
 */
function copyFileForMac(localFileUrl: string) {
  return new Promise((resolve, reject) => {
   // 文件的路径
   const filePath = path.resolve(localFileUrl);
   Logger.log(`【copyFileForMac】Copying file to clipboard: ${filePath}`)
   // 使用AppleScript将文件复制到剪贴板
   const copyFileToClipboardScript = `osascript -e 'set the clipboard to POSIX file "${filePath}"'`;
   // 执行AppleScript
   try {
    // 检查文件是否存在本地
    if (!fs.existsSync(filePath)) {
     reject(false)
     Logger.error(`【copyFileForMac】Error: File not found at path ${filePath}`);
    }
    
    exec(copyFileToClipboardScript, (error: { message: any; }, stdout: any, stderr: any) => {
     if (error) {
      reject(false)
      Logger.error(`【copyFileForMac】Error: ${error.message}`);
      return;
     }
     
     if (stderr) {
      reject(false)
      Logger.error(`【copyFileForMac】Error: ${stderr}`);
      return;
     }
     
     resolve(true)
     Logger.log('【copyFileForMac】文件已经被写入剪切板');
    });
   } catch (error) {
    Logger.error(`【copyFileForMac】Error: ${error}`);
    reject(false)
   }
  });
}

windows系统复制到剪切板

/**
 * 将文件复制到Windows系统的剪贴板
 *
 * @param localFileUrl 文件路径
 * @returns 返回一个Promise,如果成功复制到剪贴板,则resolve为true;如果失败,则reject为错误信息
 */
function copyFileForWindows(localFileUrl: string) {
  return new Promise((resolve, reject) => {
   // 文件的路径
   const filePath = path.resolve(localFileUrl);
   Logger.log(`【copyFileForWindows】Copying file to clipboard: ${filePath}`)
   // 使用powershell命令将文件复制到剪贴板
   const copyFileToClipboardScript = `${powershellBin} -command "& {Set-Clipboard -Path '${filePath}'}"`;
   // 执行powershell命令
   try {
    // 检查文件是否存在本地
    if (!fs.existsSync(filePath)) {
     reject(false)
     Logger.error(`【copyFileForMac】Error: File not found at path ${filePath}`);
    }
    
    exec(copyFileToClipboardScript, (error: { message: any; }, stdout: any, stderr: any) => {
     if (error) {
      reject(error)
      Logger.error(`【copyFileForWindows】Error: ${error.message}`);
      return;
     }
     
     if (stderr) {
      reject(stderr)
      Logger.error(`【copyFileForWindows】Error: ${stderr}`);
      return;
     }
     
     resolve(true)
     Logger.log('【copyFileForWindows】文件已经被写入剪切板');
    });
   } catch (error) {
    reject(error)
    Logger.error(`【copyFileForWindows】Error: ${error}`);
   }
  });
}

总结

electron的clipboard剪切板只支持text、html、rtf、bookmark、writeImage等,5种类型写入到剪切板,并不支持其他文件类型、如file、video、audio等等

const { clipboard } = require('electron')

clipboard.write({
  text: 'test',
  html: '<b>Hi</b>',
  rtf: '{\rtf1\utf8 text}',
  bookmark: 'a title'
})

console.log(clipboard.readText())
// 'test'

console.log(clipboard.readHTML())
// <meta charset='utf-8'><b>Hi</b>

console.log(clipboard.readRTF())
// '{\rtf1\utf8 text}'

console.log(clipboard.readBookmark())
// { title: 'a title', url: 'test' }

我们参考系统级别的复制体性,最终实现了的文件复制到剪切板功能。

能够实现的前提是,文件已经存储在用户本地设备。

补充

业务层面,如何将文件缓存到本地,则需要用到electron的WebRequest网络拦截功能,再业务层资源下拉的时候拦截对应的请求,并将资源缓存到我们指定的文件夹位置,后续复制的时候,则直接读取缓存的文件路径提供给 copy-file。

以上就是Electron实现文件复制到剪切板的方案的详细内容,更多关于Electron文件复制到剪切板的资料请关注脚本之家其它相关文章!

相关文章

  • 微信小程序自定义可滑动日历界面

    微信小程序自定义可滑动日历界面

    这篇文章主要为大家详细介绍了微信小程序自定义可滑动日历界面,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • 浅析JavaScript中的call、apply和bind方法

    浅析JavaScript中的call、apply和bind方法

    JavaScript中的call、apply和bind方法是用于改变函数执行上下文和预先设置参数的强大工具,它们在编写可维护和优雅的代码时起到了重要的作用,本文将介绍这些方法的原理和使用场景,并展示如何将它们应用于你的代码中,使其更加漂亮
    2023-06-06
  • js知识点总结之getComputedStyle的用法

    js知识点总结之getComputedStyle的用法

    getComputedStyle是一个可以获取当前元素所有最终使用的CSS属性值,下面这篇文章主要给大家介绍了关于js知识点总结之getComputedStyle用法的相关资料,需要的朋友可以参考下
    2022-10-10
  • extjs图形绘制之饼图实现方法分析

    extjs图形绘制之饼图实现方法分析

    这篇文章主要介绍了extjs图形绘制之饼图实现方法,结合实例形式分析了extjs绘制饼图的相关实现方法与操作注意事项,需要的朋友可以参考下
    2020-03-03
  • 微信小程序如何调用新闻接口实现列表循环

    微信小程序如何调用新闻接口实现列表循环

    这篇文章主要介绍了微信小程序如何调用新闻接口实现列表循环,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • 让编辑器支持word复制黏贴、截屏的js代码

    让编辑器支持word复制黏贴、截屏的js代码

    这篇文章主要为大家详细介绍了让编辑器支持word复制黏贴、截屏的js代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • javascript实现类似百度分享功能的方法

    javascript实现类似百度分享功能的方法

    这篇文章主要介绍了javascript实现类似百度分享功能的方法,以实例形式较为完整的分析了基于javascript实现百度分享功能所涉及的样式与分享功能实现方法,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • JS正则表达式修饰符中multiline(/m)用法分析

    JS正则表达式修饰符中multiline(/m)用法分析

    这篇文章主要介绍了JS正则表达式修饰符中multiline(/m)用法,结合实例形式分析了JS正则中多行模式multiline的功能、使用方法与相关注意事项,需要的朋友可以参考下
    2016-12-12
  • javascript实现点击图片切换功能

    javascript实现点击图片切换功能

    这篇文章主要为大家详细介绍了javascript实现点击图片切换功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • JavaScript事件的委托(代理)的用法示例详解

    JavaScript事件的委托(代理)的用法示例详解

    事件委托,也叫事件代理,是JavaScript中绑定事件的一种常用技巧。就是将原本需要绑定在子元素的响应事件委托给父元素或更外层元素,让外层元素担当事件监听的职务。本文将详细为大家介绍JavaScript事件委托的用法,需要的可以参考一下
    2022-01-01

最新评论