nodejs 不用 electron 实现打开文件资源管理器并选择文件

前言

最近在开发一些小脚本,用 nodejs 实现。其中很多功能需要选择一个/多个文件,或者是选择一个文件夹。

最初的实现是手动输入一个目录(这个只是一个普通的终端文本输入,所以按下 tab 没有路径提示),非常的麻烦,而且很容易输错。

这种情况下网上给出的解决方案都是 electron。但是我一个小脚本用 electron 属实有点夸张了,后来转念一想可以通过 powershell 来实现类似的功能。

通过命令唤醒文件选择器

通过 cmd / prowershell 唤醒文件选择器

对 powershell 不熟悉的我唰的一声打开了 gpt,gpt 不负众望 很快给出了答案

注意这里有区别:cmd 终端中需要调用 powershell.exe
如果当前已经是在 powershell 终端的话,直接运行对应的指令即可

  • 在 cmd 中运行:
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 中运行:
& {Add-Type -AssemblyName System.Windows.Forms; $FileDialog = New-Object System.Windows.Forms.OpenFileDialog; $result = $FileDialog.ShowDialog(); if ($result -eq 'OK') { Write-Output $FileDialog.FileName }}

运行效果:选择文件后终端会输出你选择的文件的全路径

pFSiuTJ.png

在 nodejs 调用 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 }}"`// 异步执行
exec(command, (error, file) => {console.log(error, file)
})// 同步执行
const filePath = execSync(command)
console.log('选择的文件', filePath)

到这结束了吗?并没有,我选择的是一个包含中文名称的路径,输入结果如下:

pFSiI10.png

几个小问题:

  1. execSync 同步执行的代码返回的是 Buffer 类型
    • 可以用 filePath.toString()获取实际的路径
  2. 选择的文件/文件夹包含中文,返回乱码的问题
    • 这个需要设置终端的编码类型,也就是在执行上面的命令执行先执行 chcp 650
  3. 遇到执行警告:libpng warning: iCCP: cHRM chunk does not match sRGB
    • 卸载 QQ 拼音 😃 (虽然我也不知道具体是哪里的问题,不过确实是 QQ 拼音引起的)

调整后执行效果如下:

pFSFY3q.png

如何实现多选文件 / 选择文件夹?

  • 选择目录
# 加载 Windows.Forms 程序集
Add-Type -AssemblyName System.Windows.Forms# 创建 FolderBrowserDialog 对象
$folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog# 设置对话框的属性
$folderDialog.Description = "请选择文件夹"
$folderDialog.RootFolder = [System.Environment+SpecialFolder]::MyComputer# 显示文件夹选择对话框
$result = $folderDialog.ShowDialog()# 检查用户是否点击了 "确定" 按钮
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {# 输出所选文件夹的路径Write-Output $folderDialog.SelectedPath
} else {# 用户取消选择,这里输出空路径Write-Output ""
}

合并成一行代码则是:

  • cmd 执行:
powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog; $folderDialog.Description = '请选择文件夹'; $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# 创建 OpenFileDialog 对象
$fileDialog = New-Object System.Windows.Forms.OpenFileDialog# 设置对话框的属性
$fileDialog.Multiselect = $true
$fileDialog.Title = "请选择文件"
$fileDialog.Filter = "All Files (*.*)|*.*"# 显示文件选择对话框
$result = $fileDialog.ShowDialog()# 检查用户是否点击了 "确定" 按钮
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {# 输出所选文件的路径(数组)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 = '请选择文件'; $fileDialog.Filter = 'All Files (*.*)|*.*'; $result = $fileDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $fileDialog.FileNames } else { Write-Output '' }}"

一些细节

  • 如果是选择单个文件/选择文件目录。输出的结果会包含一些前后空格和换行,所以需要通过 filePath.trim() 处理一下多余的字符
  • 如果是多选的文件,返回的是字符串,每个文件以换行隔开的,也是需要自行处理
  • 眼尖的朋友可能发现了在多选的命令中有一段代码:$fileDialog.Filter = "All Files (*.*)|*.*" 可以用于设置可选择的文件类型的。
    对应的是这个功能:
    pFSkBsf.png
    就不再细说了~ 自行摸索

MacOS 如何实现用命令打开选择器

以下的命令完全来自 GPT,并没有经过测试。自行判断代码是否正常运行 (原谅我并没有 mac)

  • 选择一个文件
osascript -e 'POSIX path of (choose file with prompt "请选择一个文件")'
  • 选择一个目录
osascript -e 'POSIX path of (choose folder with prompt "请选择一个目录")'
  • 选择多个文件
    (略)gpt 给出的答案非常的长,而且我没电脑试验,所以就不放代码了,有试验过的可以告诉我补充一下~

最后

至此,我的小脚本使用体验已经拉满,再也不用一个个输入文件路径了。

总结下所有用到的命令:

  • Windows

    • 选择单个文件
      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 = '请选择文件夹'; $folderDialog.RootFolder = [System.Environment+SpecialFolder]::MyComputer; $result = $folderDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $folderDialog.SelectedPath } else { Write-Output '' }}"
    
    • 选择多个文件
    powershell.exe -Command "& {Add-Type -AssemblyName System.Windows.Forms; $fileDialog = New-Object System.Windows.Forms.OpenFileDialog; $fileDialog.Multiselect = $true; $fileDialog.Title = '请选择文件'; $fileDialog.Filter = 'All Files (*.*)|*.*'; $result = $fileDialog.ShowDialog(); if ($result -eq [System.Windows.Forms.DialogResult]::OK) { Write-Output $fileDialog.FileNames } else { Write-Output '' }}"
    
  • MacOS

    • 选择一个文件
    osascript -e 'POSIX path of (choose file with prompt "请选择一个文件")'
    
    • 选择一个目录
    osascript -e 'POSIX path of (choose folder with prompt "请选择一个目录")'
    
    • 选择多个文件

完 ~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/603838.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UNION 和 UNION ALL

概述 UNION 和 UNION ALL 都是 SQL 中用于将多个 SELECT 语句的结果合并成一个结果集的操作符。它们都适用于需要将多个表或查询结果合并在一起的情况。但是它们的行为略有不同。 区别 UNION 和 UNION ALL 的区别在于,UNION 会将结果集合并成一个不含重复行的结果…

java springboot 目录组织架构介绍

推荐的package组织方式 com- example- myproject // root packagecom.example.myproject,所有的类和其他package都在root package之下。- Application.java // 应用主类- domain // 用于定义实体映射关系与数据访问相关的接口和实现| - Customer.java| - Custom…

实现并解决微服务间OpenFeign转发文件格式MultipartFile

场景 使用openfeign转发MultipartFile类型的文件时出现了下面的错误。 PostMapping(value "/upload", consumes MediaType.MULTIPART_FORM_DATA_VALUE) ApiOperation(value "导入") public ResponseJson<String> uploadFiles(RequestParam(&quo…

通过IP地址如何进行网络安全防护

IP地址在网络安全防护中起着至关重要的作用&#xff0c;可以用于监控、过滤和控制网络流量&#xff0c;识别潜在威胁并加强网络安全。以下是通过IP地址进行网络安全防护的一些建议&#xff1a; 1. 建立IP地址白名单和黑名单&#xff1a; 白名单&#xff1a;确保只有授权的IP地…

MySQL——用户管理

目录 一.用户管理 二.用户 1.用户信息 2.创建用户 3.删除用户 4. 修改用户密码 三.数据库的权限 1.给用户授权 2.回收权限 一.用户管理 如果我们只能使用root用户&#xff0c;root的权限非常大,这样存在安全隐患。这时&#xff0c;就需要使用MySQL的用户管理&#xff…

Java中的Stream API进阶使用

Java的Stream API是Java 8引入的一个强大的功能&#xff0c;它允许以声明性方式处理数据集合&#xff0c;例如过滤、映射、排序等。下面是一些Stream API的进阶使用&#xff1a; 自定义中间操作&#xff1a;你可以定义自己的中间操作&#xff0c;然后在Stream上使用它。例如&am…

2.5 KERNEL FUNCTIONS AND THREADING

我们现在准备讨论更多关于CUDA内核功能以及启动这些内核功能的效果。在CUDA中&#xff0c;内核函数指定所有线程在并行阶段执行的代码。由于所有这些线程执行相同的代码&#xff0c;CUDA编程是众所周知的单程序多数据&#xff08;SPMD&#xff09;[Ata 1998]并行编程风格的实例…

相交链表【哈希】【双指针】

Problem: 160. 相交链表 文章目录 思路 & 解题方法复杂度哈希技巧 思路 & 解题方法 可以用hash做&#xff0c;也可以做一个技巧。 复杂度 时间复杂度: 添加时间复杂度, 示例&#xff1a; O ( n ) O(n) O(n) 空间复杂度: 添加空间复杂度, 示例&#xff1a; O ( n ) O…

每天刷两道题——第七天+第八天

力扣官网 1.1移动零 给定一个数组 n u m s nums nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序&#xff0c;在不复制数组的情况下原地对数组进行操作。 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 代码 def moveZeroea…

强化学习的数学原理学习笔记 - 蒙特卡洛方法(Monte Carlo)

文章目录 概览&#xff1a;RL方法分类蒙特卡洛方法&#xff08;Monte Carlo&#xff0c;MC&#xff09;MC BasicMC Exploring Starts&#x1f7e6;MC ε-Greedy 本系列文章介绍强化学习基础知识与经典算法原理&#xff0c;大部分内容来自西湖大学赵世钰老师的强化学习的数学原理…

Matytype的安装问题(word及PPT报错问题)

特别针对&#xff1a;mathtype安装了多次&#xff0c;又卸载了多次的用户。 Word报弹错错误&#xff1a;参考 mathtype安装后&#xff0c;打开word出现没找到dll的错误&#xff0c;这个问题较好解决。 如何解决MathType兼容Office 2016-MathType中文网 PPT&#xff08;PowerPoi…

线程实现方式Callable_获取线程的返回结果

线程实现方式Callable_获取线程的返回结果 1、实现一个Callable接口 import java.util.concurrent.Callable;public class MyCallable implements Callable<Integer> {Overridepublic Integer call() throws Exception {int num 0;for (int i 1; i < 100; i) {num …

uViw Dialog 对话框

在保留当前页面状态的情况下&#xff0c;告知用户并承载相关操作。 TIP 在 SSR 场景下&#xff0c;您需要将组件包裹在 <client-only></client-only> 之中 (如: Nuxt) 和 SSG (e.g: VitePress). 基础用法# Dialog 弹出一个对话框&#xff0c;适合需要定制性更大…

Opencv与PyQt5设计一个摄像头界面

一、前言 本篇的内容是学习的这一位博主的&#xff1a;程序界面设计_Doc_Cheng的博客-CSDN博客。 这是我见过很详细的教你如何使用的PyQt5来完成UI界面设计的&#xff0c;专注于UI界面设计。对我而言&#xff0c;这教程就像是一个实用工具&#xff0c;因为我只需要能够显示图…

nodejs01

nodejs作用 Node.js 是一个免费的、开源的、跨平台的 JavaScript 运行时环境&#xff0c;允许开发人员在浏览器之外编写命令行工具和服务器端脚本. 是javascript的一个运行环境&#xff0c;&#xff0c;&#xff0c; nodejs stream 是前端工程化的基础 nodejs可以作为中间层&…

SpringMVC-@RequestMapping注解

0. 多个方法对应同一个请求 RequestMapping("/")public String toIndex(){return "index";}RequestMapping("/")public String toIndex2(){return "index";}这种情况是不允许的&#xff0c;会报错。 1. 注解的功能 RequestMapping注…

《程序员的自我修养--链接,装载与库》

第一章&#xff1a;温故而知新 过度优化的问题&#xff1a; 我们知道volatile关键字可以阻止过度优化&#xff0c;因为它可以完成两件事&#xff1a; 阻止编译器为了提高速度将一个变量缓存到寄存器而不写回阻止编译器调整操作volatile变量的指令顺序 然而&#xff0c;在优…

如何使用csdn中的c知道进行学习?

1.c知道 猜测是通过chatgpt训练链接到CSDN内部的文章内容等&#xff0c;进行生成的一款应用。 2.如何使用呢 打比方说&#xff0c;我想学习下多目标跟踪中的ukf&#xff0c;那么就可以输入这个关键字。 那既然是学习&#xff0c;就要进一步深究&#xff0c;有三种方式&#…

uniapp向上拉加载,下拉刷新

目录 大佬1大佬2 大佬1 大佬地址&#xff1a;https://blog.csdn.net/wendy_qx/article/details/135077822 大佬2 大佬2&#xff1a;https://blog.csdn.net/chen__hui/article/details/122497140

<软考高项备考>《论文专题 - 51 进度管理(2) 》

3 过程2-定义活动 3.1 问题 4W1H过程做什么识别和记录为完成项目可交付成果而须采取的具体行动的过程作用&#xff1a;将工作包分解为进度活动&#xff0c;作为对项目工作进行进度估算、规划、执行、监督和控制的基础为什么做对活动才能更详细更准确的分配资源、时间、成本谁…