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

Ionic 6 如何将本地file/Capacitor协议URL转换为Blob用于API上传

Ionic 6 本地文件URL转Blob的可落地解决方案

核心实现思路

由于iOS WKWebView的同源策略限制,直接通过fetch/XMLHttpRequest读取file://、capacitor://协议的本地文件会触发跨域拦截,同时旧版第三方Base64插件在iOS平台已被废弃,因此采用Capacitor官方原生Filesystem插件读取文件内容,直接转换为可用于FormData上传的Blob对象,全程无废弃API依赖,iOS/Android全平台兼容。

前置准备

  • 安装Capacitor官方Filesystem依赖:
    npm install @capacitor/filesystem
  • 同步原生工程配置:
    npx cap sync

核心通用转换函数

该函数同时兼容file://、capacitor://两类输入URL,自动解析真实磁盘路径、读取文件内容、生成对应MIME类型的Blob:

import { Filesystem } from '@capacitor/filesystem';
// 常见业务场景的文件MIME类型映射
const MIME_MAP: Record<string, string> = {
  jpg: 'image/jpeg',
  jpeg: 'image/jpeg',
  png: 'image/png',
  gif: 'image/gif',
  webp: 'image/webp',
  pdf: 'application/pdf',
  doc: 'application/msword',
  docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  xls: 'application/vnd.ms-excel',
  xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  txt: 'text/plain'
};
/**
 * 本地文件URL转Blob
 * @param fileUrl 支持两类输入:file协议URL / Capacitor协议URL
 * @returns 可直接追加到FormData的Blob对象
 */
export async function localUrlToBlob(fileUrl: string): Promise<Blob> {
  // 1. 解析原生层可识别的纯文件路径
  let rawDiskPath = '';
  if (fileUrl.startsWith('capacitor://')) {
    // 还原Capacitor协议映射的真实磁盘路径
    rawDiskPath = fileUrl.replace('capacitor://localhost/_capacitor_file_', '');
  } else if (fileUrl.startsWith('file://')) {
    // 直接剥离file协议前缀得到磁盘路径
    rawDiskPath = fileUrl.replace('file://', '');
  } else {
    throw new Error('不支持的文件URL格式');
  }
  // 2. 通过原生层读取文件内容,无WebView跨域限制
  const fileContent = await Filesystem.readFile({
    path: rawDiskPath,
    encoding: 'base64'
  });
  // 3. 将base64编码内容转换为二进制字节数组
  const base64 = fileContent.data;
  const binaryStr = window.atob(base64);
  const uint8Array = new Uint8Array(binaryStr.length);
  for (let index = 0; index < binaryStr.length; index++) {
    uint8Array[index] = binaryStr.charCodeAt(index);
  }
  // 4. 根据文件后缀匹配对应MIME类型
  const fileSuffix = rawDiskPath.split('.').pop()?.toLowerCase() || '';
  const contentType = MIME_MAP[fileSuffix] || 'application/octet-stream';
  // 5. 生成标准Blob对象
  return new Blob([uint8Array], { type: contentType });
}

接入现有上传逻辑

完全兼容现有FormData上传流程,仅需在生成FormData前调用上述工具函数获取Blob即可,无需改动原有请求封装:

async function uploadBusinessFile(fileUrl: string, fileName: string, uploadUrl: string, authKey: string) {
  // 调用工具函数拿到Blob
  const blob = await localUrlToBlob(fileUrl);
  const formData = new FormData();
  formData.append("file", blob);
  formData.append("name", fileName);
  formData.append("auth", authKey);
  return this.api.post(uploadUrl, formData, true);
}

常见避坑点

  • 不要尝试直接用WebAPI fetch 请求file:///capacitor://格式的URL,iOS WKWebView的安全策略会直接拦截这类跨域请求,抛出CORS错误
  • 替换掉原项目中使用的废弃第三方Base64插件,这类插件底层依赖的旧Cordova接口在iOS 14+版本已被官方标记为不推荐使用,存在权限访问失败的问题
  • 若需处理超大文件(100M以上),可在读取流程增加分块读取逻辑,避免一次性加载全量内容导致的内存溢出

内容的提问来源于stack exchange,提问作者Milez Zimz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 12:54:02