如何在USB设备中筛选出USB大容量存储设备?
解决USB大容量存储设备筛选为null的问题
你的筛选逻辑失效主要有两个核心原因:
- 多数U盘的设备描述符
bDeviceClass是0x00(类定义在接口层),而非0x08,直接按设备类筛选会漏掉这些设备 - 后续直接用
/dev/${endpoint.deviceDescriptor.iSerialNumber}访问设备的方式完全错误,USB存储设备需挂载到文件系统后通过挂载路径访问,不能直接操作USB端点写文件
1. 修正设备筛选逻辑
遍历设备的接口描述符(而非仅设备描述符)检查类信息,这是识别大容量存储设备的正确方式:
let usbDevice = null; for (const device of devices) { // 遍历设备所有配置 for (const config of device.configurations) { // 遍历配置下的所有接口 for (const iface of config.interfaces) { // 遍历接口的所有备用设置 for (const alt of iface.altsetting) { if ( alt.bInterfaceClass === 0x08 && // 大容量存储接口类 alt.bInterfaceSubClass === 0x06 && // SCSI透明命令集 (alt.bInterfaceProtocol === 0x50 || alt.bInterfaceProtocol === 0x01) // Bulk-only或SCSI协议 ) { usbDevice = device; break; } } if (usbDevice) break; } if (usbDevice) break; } if (usbDevice) break; }
2. 修复文件写入逻辑(关键)
usb包用于直接操作USB硬件端点,不适合直接写入文件系统。正确流程是先获取U盘挂载点,再用fs模块写入:
// 先安装依赖:npm install mount-info import { getMounts } from 'mount-info'; // 根据操作系统筛选USB挂载点 async function getUsbMountPath() { const mounts = await getMounts(); // Linux/macOS筛选vfat/ext4格式,Windows筛选可移动驱动器 return mounts.find(mount => mount.fsType === 'vfat' || mount.fsType === 'ext4' || mount.driveType === 'removable' )?.mountpoint; }
3. 调试建议
在筛选时打印每个设备的详细描述符,确认目标设备的类信息位置:
for (const device of devices) { console.log('设备描述符:', device.deviceDescriptor); device.configurations.forEach(config => { config.interfaces.forEach(iface => { iface.altsetting.forEach(alt => { console.log('接口描述符:', alt); }); }); }); }
修改后的完整代码示例
import { usb, getDeviceList } from "usb"; import fs from "fs"; import path from "path"; import { getMounts } from 'mount-info'; async function getUsbMountPath() { const mounts = await getMounts(); return mounts.find(mount => mount.fsType === 'vfat' || mount.fsType === 'ext4' || mount.driveType === 'removable' )?.mountpoint; } async function path2usb(selectedMeasures) { try { usb.on("attach", (device) => { console.log("USB设备已连接:", device.deviceDescriptor.idVendor.toString(16), device.deviceDescriptor.idProduct.toString(16)); }); usb.on("detach", (device) => { console.log("USB设备已断开:", device.deviceDescriptor.idVendor.toString(16), device.deviceDescriptor.idProduct.toString(16)); }); const devices = getDeviceList(); let usbDevice = null; // 修正后的设备筛选逻辑 for (const device of devices) { for (const config of device.configurations) { for (const iface of config.interfaces) { for (const alt of iface.altsetting) { if ( alt.bInterfaceClass === 0x08 && alt.bInterfaceSubClass === 0x06 && (alt.bInterfaceProtocol === 0x50 || alt.bInterfaceProtocol === 0x01) ) { usbDevice = device; break; } } if (usbDevice) break; } if (usbDevice) break; } if (usbDevice) break; } console.log("找到的USB设备:", usbDevice); if (!usbDevice) throw new Error("未找到USB大容量存储设备!"); // 获取挂载点 const mountPath = await getUsbMountPath(); if (!mountPath) throw new Error("USB设备未挂载到文件系统!"); const folderName = selectedMeasures.join("_"); const targetFilePath = path.join(mountPath, `${folderName}.txt`); fs.writeFileSync(targetFilePath, selectedMeasures.join("\n")); console.log(`数据已导出到USB设备: ${targetFilePath}`); return targetFilePath; } catch (error) { console.error("导出数据到USB设备失败:", error.message); throw error; } } export { path2usb };
内容的提问来源于stack exchange,提问作者Olivia
相关产品推荐
相关产品推荐

