【Electron】如何读取剪切板上的文件数据

2,047 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

一、前言

本篇文章主要介绍如何获取剪切板上的文件数据,主要是通过electron的clipboard模块来实现的。

二、实现方案

主要有以下技术要点:

  1. 在MacOS系统中,能通过clipboard.read('NSFilenamesPboardType')读取到一个被复制的文件或文件夹列表的XML格式描述文本。
  2. 在windows系统中,能通过clipboard.read('CF_HDROP')读取剪切板的上的文件名数组。
  3. 在MacOS系统中,能通过clipboard.read('public.file-url')读取剪切板上的单个文件。
  4. 在windoows系统中能通过clipboard.read('FileNameW')读取剪切板上单个文件。
  5. 通过clipboard.readImage('clipboard')能获取剪切板上的图片。

这其中,在windows系统中读取含有中文名称时,路径格式会有问题,因此在读取文件信息的时候需要如下写法,多文件同理

clipboard.readBuffer('FileNameW').toString('ucs2').replace(RegExp(String.fromCharCode(0), 'g'), '')

electron中读取剪切板上文件信息,完整版实现代码如下

const { clipboard } = window.require('electron').remote
// 获取剪切板上文件路径
getClipboardFiles () {
  console.log('Files from clipboard')
  // 用于存放剪切板上的文件路径集合
  let filePath = []
  if (this.$isMac) { // 若当前在mac系统中
    if (clipboard.has('NSFilenamesPboardType')) { // 若存在多个文件
      const tagContent = clipboard.read('NSFilenamesPboardType').match(/<string>.*<\/string>/g)
      filePath = tagContent ? tagContent.map(item => item.replace(/<string>|<\/string>/g, '')) : []
    } else { // 仅单个文件的时候
      const clipboardImage = clipboard.readImage('clipboard')
      if (!clipboardImage.isEmpty()) { // 若此文件为图片
        console.log('upload image from clipboard')
        const png = clipboardImage.toPNG()
        const fileInfo = {
          buffer: png,
          mimetype: 'image/png',
          originalname: uuid(8, 16) + '.png'
        }
        filePath = [fileInfo]
      } else { // 读取单个文件
        filePath = [clipboard.read('public.file-url').replace('file://', '')].filter(item => item)
      }
    }
  } else { // 若当前在windows系统中
    if (clipboard.has('CF_HDROP')) { // 若剪切板上有多个文件
      const rawFilePathStr = clipboard.readBuffer('CF_HDROP').toString('ucs2') || ''
      let formatFilePathStr = [...rawFilePathStr]
        .filter((_, index) => rawFilePathStr.charCodeAt(index) !== 0)
        .join('')
        .replace(/\\/g, '\\')

      const drivePrefix = formatFilePathStr.match(/[a-zA-Z]:\\/)

      if (drivePrefix) {
        const drivePrefixIndex = formatFilePathStr.indexOf(drivePrefix[0])
        if (drivePrefixIndex !== 0) {
          formatFilePathStr = formatFilePathStr.substring(drivePrefixIndex)
        }
        filePath = formatFilePathStr
          .split(drivePrefix[0])
          .filter(item => item)
          .map(item => drivePrefix + item)
      }
    } else { // 若为单个文件
      const clipboardImage = clipboard.readImage('clipboard')
      if (!clipboardImage.isEmpty()) { // 当前文件为图片类型
        console.log('upload image from clipboard')
        const png = clipboardImage.toPNG()
        const fileInfo = {
          buffer: png,
          mimetype: 'image/png',
          originalname: uuid(8, 16) + '.png'
        }
        filePath = [fileInfo]
      } else { // 读取单个文件
        filePath = [
          clipboard.readBuffer('FileNameW').toString('ucs2').replace(RegExp(String.fromCharCode(0), 'g'), '')
        ].filter(item => item)
      }
    }
  }
  console.log('get file path from clipboard:', filePath)
  return filePath
}

我们通过以上方法能获取到剪切板上的文件路径,后续可以通过fs.read()方法读取文件信息,进行对应的文件操作。

三、后记

在剪切板这一部分,electron的api说明并不明确。因此找了许多关于剪切板的资料。

参考资料

  1. learn.microsoft.com/en-us/windo…
  2. www.codeproject.com/Reference/1…
  3. github.com/electron/el…
  4. github.com/electron/el…
  5. github.com/electron/el…

本篇完结! 撒花 ! 感谢观看! 希望能帮助到你!