nodejs不用electron實(shí)現(xiàn)打開文件資源管理器并選擇文件
前言
最近在開發(fā)一些小腳本,用 nodejs 實(shí)現(xiàn)。其中很多功能需要選擇一個(gè)/多個(gè)文件,或者是選擇一個(gè)文件夾。
最初的實(shí)現(xiàn)是手動(dòng)輸入一個(gè)目錄(這個(gè)只是一個(gè)普通的終端文本輸入,所以按下 tab 沒有路徑提示),非常的麻煩,而且很容易輸錯(cuò)。
這種情況下網(wǎng)上給出的解決方案都是 electron。但是我一個(gè)小腳本用 electron 屬實(shí)有點(diǎn)夸張了,后來轉(zhuǎn)念一想可以通過 powershell 來實(shí)現(xiàn)類似的功能。
通過命令喚醒文件選擇器
通過 cmd / prowershell 喚醒文件選擇器
對(duì) powershell 不熟悉的我唰的一聲打開了 gpt,gpt 不負(fù)眾望 很快給出了答案
注意這里有區(qū)別:cmd 終端中需要調(diào)用
powershell.exe
如果當(dāng)前已經(jīng)是在 powershell 終端的話,直接運(yùn)行對(duì)應(yīng)的指令即可
- 在 cmd 中運(yùn)行:
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $FileDialog = New-Object System.Windows.Forms.OpenFileDialog; $result = $FileDialog.ShowDialog(); if ($result -eq 'OK') { Write-Output $FileDialog.FileName }}"
- 在 powershell 中運(yùn)行:
& {Add-Type -AssemblyName System.Windows.Forms; $FileDialog = New-Object System.Windows.Forms.OpenFileDialog; $result = $FileDialog.ShowDialog(); if ($result -eq 'OK') { Write-Output $FileDialog.FileName }}
運(yùn)行效果:選擇文件后終端會(huì)輸出你選擇的文件的全路徑
在 nodejs 調(diào)用 cmd 命令
const { exec, execSync } = require('child_process') const command = `powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $FileDialog = New-Object System.Windows.Forms.OpenFileDialog; $result = $FileDialog.ShowDialog(); if ($result -eq 'OK') { Write-Output $FileDialog.FileName }}"` // 異步執(zhí)行 exec(command, (error, file) => { console.log(error, file) }) // 同步執(zhí)行 const filePath = execSync(command) console.log('選擇的文件', filePath)
到這結(jié)束了嗎?并沒有,我選擇的是一個(gè)包含中文名稱的路徑,輸入結(jié)果如下:
幾個(gè)小問題:
- execSync 同步執(zhí)行的代碼返回的是
Buffer
類型- 可以用
filePath.toString()
獲取實(shí)際的路徑
- 可以用
- 選擇的文件/文件夾包含中文,返回亂碼的問題
- 這個(gè)需要設(shè)置終端的編碼類型,也就是在執(zhí)行上面的命令執(zhí)行先執(zhí)行
chcp 650
- 這個(gè)需要設(shè)置終端的編碼類型,也就是在執(zhí)行上面的命令執(zhí)行先執(zhí)行
- 遇到執(zhí)行警告:
libpng warning: iCCP: cHRM chunk does not match sRGB
- 卸載 QQ 拼音(雖然我也不知道具體是哪里的問題,不過確實(shí)是 QQ 拼音引起的)
調(diào)整后執(zhí)行效果如下:
如何實(shí)現(xiàn)多選文件 / 選擇文件夾?
- 選擇目錄
# 加載 Windows.Forms 程序集 Add-Type -AssemblyName System.Windows.Forms # 創(chuàng)建 FolderBrowserDialog 對(duì)象 $folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog # 設(shè)置對(duì)話框的屬性 $folderDialog.Description = "請(qǐng)選擇文件夾" $folderDialog.RootFolder = [System.Environment+SpecialFolder]::MyComputer # 顯示文件夾選擇對(duì)話框 $result = $folderDialog.ShowDialog() # 檢查用戶是否點(diǎn)擊了 "確定" 按鈕 if ($result -eq [System.Windows.Forms.DialogResult]::OK) { # 輸出所選文件夾的路徑 Write-Output $folderDialog.SelectedPath } else { # 用戶取消選擇,這里輸出空路徑 Write-Output "" }
合并成一行代碼則是:
- cmd 執(zhí)行:
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog; $folderDialog.Description = '請(qǐng)選擇文件夾'; $folderDialog.RootFolder = [System.Environment+SpecialFolder]::MyComputer; $result = $folderDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $folderDialog.SelectedPath } else { Write-Output '' }}"
多選文件同理:
# 加載 Windows.Forms 程序集 Add-Type -AssemblyName System.Windows.Forms # 創(chuàng)建 OpenFileDialog 對(duì)象 $fileDialog = New-Object System.Windows.Forms.OpenFileDialog # 設(shè)置對(duì)話框的屬性 $fileDialog.Multiselect = $true $fileDialog.Title = "請(qǐng)選擇文件" $fileDialog.Filter = "All Files (*.*)|*.*" # 顯示文件選擇對(duì)話框 $result = $fileDialog.ShowDialog() # 檢查用戶是否點(diǎn)擊了 "確定" 按鈕 if ($result -eq [System.Windows.Forms.DialogResult]::OK) { # 輸出所選文件的路徑(數(shù)組) Write-Output $fileDialog.FileNames } else { # 用戶取消選擇 Write-Output "" }
合并為一行命令:
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $fileDialog = New-Object System.Windows.Forms.OpenFileDialog; $fileDialog.Multiselect = $true; $fileDialog.Title = '請(qǐng)選擇文件'; $fileDialog.Filter = 'All Files (*.*)|*.*'; $result = $fileDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $fileDialog.FileNames } else { Write-Output '' }}"
一些細(xì)節(jié)
- 如果是選擇單個(gè)文件/選擇文件目錄。輸出的結(jié)果會(huì)包含一些前后空格和換行,所以需要通過
filePath.trim()
處理一下多余的字符 - 如果是多選的文件,返回的是字符串,每個(gè)文件以換行隔開的,也是需要自行處理
- 眼尖的朋友可能發(fā)現(xiàn)了在多選的命令中有一段代碼:
$fileDialog.Filter = "All Files (*.*)|*.*"
可以用于設(shè)置可選擇的文件類型的。
對(duì)應(yīng)的是這個(gè)功能:
- 就不再細(xì)說了~ 自行摸索
MacOS 如何實(shí)現(xiàn)用命令打開選擇器
以下的命令完全來自 GPT,并沒有經(jīng)過測(cè)試。自行判斷代碼是否正常運(yùn)行 (原諒我并沒有 mac)
- 選擇一個(gè)文件
osascript -e 'POSIX path of (choose file with prompt "請(qǐng)選擇一個(gè)文件")'
- 選擇一個(gè)目錄
osascript -e 'POSIX path of (choose folder with prompt "請(qǐng)選擇一個(gè)目錄")'
- 選擇多個(gè)文件
(略)gpt 給出的答案非常的長(zhǎng),而且我沒電腦試驗(yàn),所以就不放代碼了,有試驗(yàn)過的可以告訴我補(bǔ)充一下~
最后
至此,我的小腳本使用體驗(yàn)已經(jīng)拉滿,再也不用一個(gè)個(gè)輸入文件路徑了。
總結(jié)下所有用到的命令:
Windows
- 選擇單個(gè)文件
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $FileDialog = New-Object System.Windows.Forms.OpenFileDialog; $result = $FileDialog.ShowDialog(); if ($result -eq 'OK') { Write-Output $FileDialog.FileName }}"
- 選擇文件目錄
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog; $folderDialog.Description = '請(qǐng)選擇文件夾'; $folderDialog.RootFolder = [System.Environment+SpecialFolder]::MyComputer; $result = $folderDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $folderDialog.SelectedPath } else { Write-Output '' }}"
- 選擇多個(gè)文件
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $fileDialog = New-Object System.Windows.Forms.OpenFileDialog; $fileDialog.Multiselect = $true; $fileDialog.Title = '請(qǐng)選擇文件'; $fileDialog.Filter = 'All Files (*.*)|*.*'; $result = $fileDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $fileDialog.FileNames } else { Write-Output '' }}"
MacOS
- 選擇一個(gè)文件
osascript -e 'POSIX path of (choose file with prompt "請(qǐng)選擇一個(gè)文件")'
- 選擇一個(gè)目錄
osascript -e 'POSIX path of (choose folder with prompt "請(qǐng)選擇一個(gè)目錄")'
- 選擇多個(gè)文件
以上就是nodejs不用electron實(shí)現(xiàn)打開文件資源管理器并選擇文件的詳細(xì)內(nèi)容,更多關(guān)于nodejs實(shí)現(xiàn)打開文件資源管理器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
node.js中的path.isAbsolute方法使用說明
這篇文章主要介紹了node.js中的path.isAbsolute方法使用說明,本文介紹了path.isAbsolute的方法說明、語法、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12node.js使用Moment.js js 時(shí)間計(jì)算方法示例小結(jié)
這篇文章主要介紹了node.js使用Moment.js js 時(shí)間計(jì)算方法,結(jié)合實(shí)例形式分析了Moment.js js模塊時(shí)間計(jì)算的常用操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2023-05-05Node.js創(chuàng)建一個(gè)Express服務(wù)的方法詳解
這篇文章主要介紹了Node.js創(chuàng)建一個(gè)Express服務(wù)的方法,結(jié)合實(shí)例形式分析了node.js創(chuàng)建Express服務(wù)的具體步驟、實(shí)現(xiàn)方法及相關(guān)操作技巧,需要的朋友可以參考下2020-01-01Koa2中間件的作用及路由實(shí)現(xiàn)實(shí)例詳解
這篇文章主要介紹了Koa2中間件的作用及路由實(shí)現(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Node.js HTTP服務(wù)器中的文件、圖片上傳的方法
這篇文章主要介紹了Node.js HTTP服務(wù)器中的文件、圖片上傳的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Node.js實(shí)現(xiàn)下載文件的兩種實(shí)用方式
最近優(yōu)化了幾個(gè)新人寫出的動(dòng)態(tài)表格文件下載接口的性能瓶頸,感覺非常有必要總結(jié)一篇文章作為文檔來拋磚引玉,這篇文章主要給大家介紹了關(guān)于Node.js實(shí)現(xiàn)下載文件的兩種實(shí)用方式,需要的朋友可以參考下2022-09-09Express.js 全局錯(cuò)誤處理實(shí)現(xiàn)
本文主要介紹了Express.js 全局錯(cuò)誤處理實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06