当前位置: 代码网 > it编程>编程语言>Javascript > Electron实现文件复制到剪切板的方案

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

2024年11月25日 Javascript 我要评论
前言electron的剪切板没有提供文件、音频、视频等等类型的支持。技术调研我们在mac、windows系统中,右键本地文件是支持复制的,并写入到剪切板的速度很快。基于这个方向,我们查找到了如下方法:

前言

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文件复制到剪切板的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com