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

如何使用jQuery无HTML接口读取本地文件上传并获取Blob正确MIME类型

本地路径无控件读取文件上传实现方案

首先明确运行环境边界:
浏览器端受同源沙箱安全策略限制,禁止JavaScript直接读取本地任意路径的文件,必须经过用户主动触发文件选择、文件拖拽等授权操作才能访问文件内容,不存在可稳定使用的绕过方案。你代码中使用的fs是Node.js runtime的原生API,仅能在Node.js、Electron等桌面端运行环境中使用。

下面分两种场景给出可直接运行的实现:

一、Node.js/Electron环境实现

你之前的代码存在三个问题:

  • 创建Blob时没有显式传入MIME类型参数
  • 打开的文件描述符没有手动关闭,会造成资源泄漏
  • append到FormData时没有传入真实文件名,服务端会默认把文件命名为blob

正确实现代码(Node 18+ 原生支持Blob、fetch,无需额外依赖)

const fs = require('fs/promises');
const path = require('path');

// 常用后缀与MIME类型映射,如果你需要覆盖更多类型,可以安装mime包,调用mime.getType(filePath)直接获取
const MIME_MAP = {
  '.txt': 'text/plain',
  '.png': 'image/png',
  '.jpg': 'image/jpeg',
  '.jpeg': 'image/jpeg',
  '.gif': 'image/gif',
  '.pdf': 'application/pdf',
  '.doc': 'application/msword',
  '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  '.zip': 'application/zip'
};

async function uploadFile(localPath, uploadUrl) {
  // 读取文件二进制内容
  const fileBuffer = await fs.readFile(localPath);
  // 获取文件名、后缀,匹配MIME类型
  const fileName = path.basename(localPath);
  const ext = path.extname(localPath).toLowerCase();
  const mimeType = MIME_MAP[ext] || 'application/octet-stream'; // 未知类型默认用二进制流
  // 构造带正确MIME的Blob对象
  const fileBlob = new Blob([fileBuffer], { type: mimeType });
  // 构造上传表单
  const formData = new FormData();
  formData.append("test", "[69]");
  formData.append("file", fileBlob, fileName);
  // 发起请求,如果你用jQuery,保持原来的processData:false、contentType:false配置即可
  return fetch(uploadUrl, {
    method: 'POST',
    body: formData
  });
}

// 调用示例
// uploadFile('C:/test.txt', 'https://你的上传接口地址')

如果你需要用同步写法,修正后的代码如下:

const fs = require('fs');
const path = require('path');

const localPath = 'C:/test.txt';
const fd = fs.openSync(localPath, 'r');
const stat = fs.statSync(localPath);
const buf = Buffer.alloc(stat.size);
fs.readSync(fd, buf, 0, stat.size, 0);
fs.closeSync(fd); // 必须手动关闭文件描述符

const fileName = path.basename(localPath);
const ext = path.extname(localPath).toLowerCase();
const mimeType = MIME_MAP[ext] || 'application/octet-stream';
const fileBlob = new Blob([buf], { type: mimeType });
formData.append('file', fileBlob, fileName);

二、纯浏览器环境实现

纯浏览器环境下无法直接读取指定本地路径的文件,如果不想显示原生文件输入控件,可以通过隐藏input、用自定义按钮触发选择事件的方式实现,本质还是走用户主动授权的流程,不存在安全问题,示例代码:

<!-- 隐藏原生文件选择控件 -->
<input type="file" id="fileInput" style="display:none">
<button id="uploadBtn">点击上传文件</button>

<script>
const fileInput = document.getElementById('fileInput');
document.getElementById('uploadBtn').addEventListener('click', () => {
  fileInput.click();
});

fileInput.addEventListener('change', (e) => {
  const selectFile = e.target.files[0];
  // 选中的File对象本身自带正确的MIME类型、文件名,直接构造表单上传即可
  const formData = new FormData();
  formData.append('file', selectFile);
  // 发起上传请求
  $.ajax({
    url: 'https://你的上传接口地址',
    method: 'POST',
    processData: false,
    contentType: false,
    data: formData
  });
});
</script>

补充说明

  • 如果需要防止用户修改文件后缀伪造MIME类型,可以增加文件魔数校验逻辑:读取文件前2-4个字节的特征值判断真实文件类型,比如PNG文件开头固定为89 50 4E 47、JPG开头固定为FF D8 FF,简单场景下用后缀匹配足够。
  • 不要把所有文件的MIME都硬编码为text/plain或者application/octet-stream,会导致服务端无法正确识别、处理文件。

内容的提问来源于stack exchange,提问作者Mauro Brx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:51:45