You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 11:41:03