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

Ionic 6中使用Fetch上传图片失败:无法向服务器发送图片数据

解决Ionic 6中Fetch无法发送图片数据的问题

直接将file://路径字符串添加到FormData是无效的,FormData要求传入File或Blob对象而非路径字符串。以下是具体解决方案:

核心步骤

  1. 读取本地图片文件内容,转换为Blob对象
  2. 将Blob对象添加到FormData后发送请求

方案一:使用Capacitor Filesystem插件(推荐)

1. 安装插件

npm install @capacitor/filesystem

2. 完整代码实现

import { Filesystem } from '@capacitor/filesystem';

async uploadAvatar(pathImage: string, token: string) {
  try {
    // 移除file://前缀,适配Capacitor文件路径规则
    const filePath = pathImage.replace('file://', '');
    
    // 读取文件内容(默认返回base64格式)
    const fileData = await Filesystem.readFile({
      path: filePath
    });
    
    // 将base64转为Blob对象
    const blob = this.base64ToBlob(fileData.data, 'image/jpeg');
    
    // 构建FormData并添加Blob(第三个参数为可选文件名)
    const formData = new FormData();
    formData.append('photo', blob, 'avatar.jpg');
    
    // 发送POST请求
    const response = await fetch(`${this.MAIN_URL}/uploadAvatar?token=${token}`, {
      method: 'POST',
      body: formData
    });
    
    const data = await response.json();
    alert(JSON.stringify(data));
  } catch (error) {
    alert(JSON.stringify(error));
  }
}

// 辅助函数:base64转Blob
private base64ToBlob(base64: string, contentType: string): Blob {
  const byteChars = atob(base64);
  const byteArrays: Uint8Array[] = [];

  for (let offset = 0; offset < byteChars.length; offset += 512) {
    const slice = byteChars.slice(offset, offset + 512);
    const byteNums = new Array(slice.length);
    
    for (let i = 0; i < slice.length; i++) {
      byteNums[i] = slice.charCodeAt(i);
    }
    
    byteArrays.push(new Uint8Array(byteNums));
  }

  return new Blob(byteArrays, { type: contentType });
}

方案二:使用Ionic Native File插件

1. 安装插件

npm install @ionic-native/file
ionic cap sync

2. 代码实现

import { File } from '@ionic-native/file/ngx';

constructor(private file: File) {}

async uploadAvatar(pathImage: string, token: string) {
  try {
    // 拆分文件路径和文件名
    const path = pathImage.substring(0, pathImage.lastIndexOf('/') + 1);
    const fileName = pathImage.substring(pathImage.lastIndexOf('/') + 1);
    
    // 直接读取文件为Blob对象
    const blob = await this.file.readAsBlob(path, fileName);
    
    // 构建FormData并发送请求
    const formData = new FormData();
    formData.append('photo', blob, fileName);
    
    const response = await fetch(`${this.MAIN_URL}/uploadAvatar?token=${token}`, {
      method: 'POST',
      body: formData
    });
    
    const data = await response.json();
    alert(JSON.stringify(data));
  } catch (error) {
    alert(JSON.stringify(error));
  }
}

注意事项

  • 权限配置:Android端需在android/app/src/main/AndroidManifest.xml中添加文件读取权限:
    <!-- Android 12及以下 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- Android 13+ -->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    
  • 服务器端校验:确保服务器正确处理multipart/form-data类型请求,能够接收photo字段的文件数据。

内容的提问来源于stack exchange,提问作者Roddy P. Carbonell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:20:19