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

Ionic Camera使用FILE_URI上传S3时文件损坏问题求助

Fixing Corrupted S3 Uploads with FILE_URI in Ionic 3 + Cordova Camera 4.0.2

Hey there, let's break down why your photos are getting corrupted when using FILE_URI and how to fix it. I've run into this exact issue before, so I know the frustration!

Why This Happens

When you set destinationType: FILE_URI, the Camera plugin returns a local file path (like file:///storage/emulated/0/Android/data/com.your.app/cache/IMG_1234.jpg) instead of the actual image data. If you try to upload this path string directly to S3, you're just sending the text of the path—not the binary image file. That's why your uploads are only ~100B and corrupted.

DATA_URL works because it returns the image as a base64-encoded string, which is the actual image content that S3 can parse.

Step-by-Step Fix

To make FILE_URI work, you need to read the actual file content from that local URI using the cordova-plugin-file plugin, then upload the binary data to S3. Here's how to do it:

1. Install the File Plugin

First, add the Cordova File plugin to your project:

cordova plugin add cordova-plugin-file

2. Update Your Code to Read and Upload the File

Replace your existing camera/upload code with this. It reads the file from the FILE_URI path, converts it to a Blob, and prepares it for S3 upload:

import { Camera, CameraOptions } from '@ionic-native/camera';
import { File } from '@ionic-native/file';
import { HttpClient } from '@angular/common/http';

// Inject these in your component's constructor
constructor(
  private camera: Camera, 
  private file: File,
  private http: HttpClient
) {}

async takePhotoAndUploadToS3() {
  const cameraOptions: CameraOptions = {
    quality: 80,
    destinationType: this.camera.DestinationType.FILE_URI,
    encodingType: this.camera.EncodingType.JPEG,
    mediaType: this.camera.MediaType.PICTURE,
    correctOrientation: true // Optional: fixes rotated photos
  };

  try {
    // Get the file URI from the camera
    const fileUri = await this.camera.getPicture(cameraOptions);
    
    // Resolve the URI to a file entry
    const fileEntry = await this.file.resolveLocalFileSystemURL(fileUri);
    
    // Get the file object from the entry
    const file = await new Promise<File>((resolve, reject) => {
      fileEntry.file(resolve, reject);
    });
    
    // Read the file as an ArrayBuffer (binary data)
    const fileBuffer = await new Promise<ArrayBuffer>((resolve, reject) => {
      const reader = new FileReader();
      reader.onloadend = () => resolve(reader.result as ArrayBuffer);
      reader.onerror = reject;
      reader.readAsArrayBuffer(file);
    });
    
    // Convert the buffer to a Blob for upload
    const blob = new Blob([fileBuffer], { type: file.type });
    
    // Create FormData (S3 usually accepts multipart/form-data uploads)
    const formData = new FormData();
    formData.append('file', blob, `photo-${Date.now()}.jpg`); // Add a unique filename
    
    // Upload to S3 (replace with your S3 pre-signed URL or upload endpoint)
    const uploadResponse = await this.http.put(
      'https://your-s3-bucket.s3.amazonaws.com/your-path',
      formData,
      { headers: { 'Content-Type': 'multipart/form-data' } }
    ).toPromise();
    
    console.log('Upload successful!', uploadResponse);
  } catch (error) {
    console.error('Error during photo/upload:', error);
  }
}

3. Key Notes to Avoid Issues

  • Permissions: Make sure your app has the necessary file access permissions. For Android, add these to config.xml:
    <platform name="android">
      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    </platform>
    
    For iOS, add these to config.xml to request photo library access:
    <platform name="ios">
      <config-file parent="NSPhotoLibraryUsageDescription" platform="ios" target="*-Info.plist">
        <string>Need photo access to take and upload photos</string>
      </config-file>
    </platform>
    
  • Platform Compatibility: The resolveLocalFileSystemURL method handles both Android's content:// URIs and iOS's file:// URIs, so you don't need to write platform-specific path conversion code.
  • S3 Upload Requirements: If you're using a pre-signed URL for S3, make sure the HTTP method (PUT/POST) matches what the pre-signed URL expects. Also, verify that the Content-Type header matches the image's MIME type (like image/jpeg).

Why Not Just Use DATA_URL?

While DATA_URL works, it's not ideal for large photos because base64 encoding increases the file size by ~30%. Using FILE_URI with binary uploads is more efficient, especially for high-resolution images.

Let me know if you run into any kinks with this setup—I’m happy to help troubleshoot further!

内容的提问来源于stack exchange,提问作者Dean or Din

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:03:51