Electron實(shí)現(xiàn)文件復(fù)制到剪切板的方案
前言
electron的剪切板沒(méi)有提供文件、音頻、視頻等等類型的支持。
技術(shù)調(diào)研
我們?cè)趍ac、windows系統(tǒng)中,右鍵本地文件是支持復(fù)制的,并寫入到剪切板的速度很快。
基于這個(gè)方向,我們查找到了如下方法:
window:使用powershell腳本命令,可以實(shí)現(xiàn)文件復(fù)制
`powershell -command "& {Set-Clipboard -Path '${filePath}'}"`
mac:使用osascript腳本指令,可以實(shí)現(xiàn)文件復(fù)制
`osascript -e 'set the clipboard to POSIX file "${filePath}"'`
注意點(diǎn)
powershell和asascript在兩個(gè)平臺(tái)支持復(fù)制文件、音頻、視頻等等,前提條件都是需要文件已經(jīng)存在于本地。
所以,我們復(fù)制的內(nèi)容必須先現(xiàn)在到本地,再進(jìn)行復(fù)制到剪切板。
實(shí)現(xiàn)方案
渲染層提供preload
contextBridge.exposeInMainWorld("mainWindowAPI", { copyFile: (filePath:string) => ipcRenderer.invoke('copy-file', filePath) });
復(fù)制的實(shí)際,需要傳遞已經(jīng)緩存到本地的文件路徑;
主進(jìn)程接收ipc
// 復(fù)制文件到剪切板 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】復(fù)制base64成功`) event.reply("copy-file", true); } catch (error) { Logger.log(`【copy-file】復(fù)制base64失敗 ${error}`) event.reply("copy-file", false); } return } // 檢查是否為本地路徑,如果不是本地路徑則退出 if(filePath.includes('file://')) { event.reply("copy-file", false); return; } // 執(zhí)行復(fù)制操作 copyFile(filePath.replace("file:///", "")).then((res: boolean) => { event.reply("copy-file", res); }).catch(() => { event.reply("copy-file", false); }) });
1.檢查filePath是否存在,不存在則退出
2.如果是base64圖片,則使用electron的nativeImage轉(zhuǎn)換成為PNG圖片(或者jpg等,可以看官網(wǎng))
3.檢查是否為本地路徑,如果不是本地路徑則退出,因?yàn)閺?fù)制到剪切板必須是本地文件,網(wǎng)絡(luò)連接是不支持的
4.是本地連接,去除file:///頭,只需要后面的文件路徑,路徑如下:/Users/自己設(shè)備的賬戶名/Library/Application Support/應(yīng)用名稱/Cache/test.dmg
檢查不同平臺(tái)
/** * 復(fù)制文件到剪貼板 * * @param localFileUrl 本地文件URL * @returns 復(fù)制結(jié)果,成功為true,失敗為false */ export function copyFile(localFileUrl: string) { if (process.platform === 'darwin') { return copyFileForMac(localFileUrl); } else if (process.platform === 'win32') { return copyFileForWindows(localFileUrl) } }
mac系統(tǒng)復(fù)制到剪切板
/** * 將文件復(fù)制到Mac的剪貼板 * * @param localFileUrl 本地文件的URL路徑 * @returns 返回一個(gè)Promise,成功時(shí)返回true,失敗時(shí)返回錯(cuò)誤消息 */ function copyFileForMac(localFileUrl: string) { return new Promise((resolve, reject) => { // 文件的路徑 const filePath = path.resolve(localFileUrl); Logger.log(`【copyFileForMac】Copying file to clipboard: ${filePath}`) // 使用AppleScript將文件復(fù)制到剪貼板 const copyFileToClipboardScript = `osascript -e 'set the clipboard to POSIX file "${filePath}"'`; // 執(zhí)行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】文件已經(jīng)被寫入剪切板'); }); } catch (error) { Logger.error(`【copyFileForMac】Error: ${error}`); reject(false) } }); }
windows系統(tǒng)復(fù)制到剪切板
/** * 將文件復(fù)制到Windows系統(tǒng)的剪貼板 * * @param localFileUrl 文件路徑 * @returns 返回一個(gè)Promise,如果成功復(fù)制到剪貼板,則resolve為true;如果失敗,則reject為錯(cuò)誤信息 */ function copyFileForWindows(localFileUrl: string) { return new Promise((resolve, reject) => { // 文件的路徑 const filePath = path.resolve(localFileUrl); Logger.log(`【copyFileForWindows】Copying file to clipboard: ${filePath}`) // 使用powershell命令將文件復(fù)制到剪貼板 const copyFileToClipboardScript = `${powershellBin} -command "& {Set-Clipboard -Path '${filePath}'}"`; // 執(zhí)行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】文件已經(jīng)被寫入剪切板'); }); } catch (error) { reject(error) Logger.error(`【copyFileForWindows】Error: ${error}`); } }); }
總結(jié)
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' }
我們參考系統(tǒng)級(jí)別的復(fù)制體性,最終實(shí)現(xiàn)了的文件復(fù)制到剪切板功能。
能夠?qū)崿F(xiàn)的前提是,文件已經(jīng)存儲(chǔ)在用戶本地設(shè)備。
補(bǔ)充
業(yè)務(wù)層面,如何將文件緩存到本地,則需要用到electron的WebRequest網(wǎng)絡(luò)攔截功能,再業(yè)務(wù)層資源下拉的時(shí)候攔截對(duì)應(yīng)的請(qǐng)求,并將資源緩存到我們指定的文件夾位置,后續(xù)復(fù)制的時(shí)候,則直接讀取緩存的文件路徑提供給 copy-file。
以上就是Electron實(shí)現(xiàn)文件復(fù)制到剪切板的方案的詳細(xì)內(nèi)容,更多關(guān)于Electron文件復(fù)制到剪切板的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript實(shí)現(xiàn)表格表單的隨機(jī)選擇和簡(jiǎn)單的隨機(jī)點(diǎn)名
本文主要介紹了JavaScript實(shí)現(xiàn)表格表單的隨機(jī)選擇和簡(jiǎn)單的隨機(jī)點(diǎn)名,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08js判斷是否為數(shù)組的函數(shù): isArray()
像 Ajaxian,StackOverflow 等,搜一下,到處都在討論 isArray() 的實(shí)現(xiàn)。對(duì)于一切都是對(duì)象的 JavaScript 來(lái)說(shuō),確實(shí)有點(diǎn)麻煩2011-10-10使用javascript實(shí)現(xiàn)Iframe自適應(yīng)高度
這篇文章主要介紹了使用javascript實(shí)現(xiàn)Iframe自適應(yīng)高度,需要的朋友可以參考下2014-12-12JavaScript navigator.userAgent獲取瀏覽器信息案例講解
這篇文章主要介紹了JavaScript navigator.userAgent獲取瀏覽器信息案例講解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08探析瀏覽器執(zhí)行JavaScript腳本加載與代碼執(zhí)行順序
本文主要基于向HTML頁(yè)面引入JavaScript的幾種方式,分析HTML中JavaScript腳本的執(zhí)行順序問(wèn)題,通過(guò)本文給大家分享瀏覽器執(zhí)行JavaScript腳本加載與代碼執(zhí)行順序,對(duì)瀏覽器執(zhí)行javascript及執(zhí)行順序相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-01-01