Fix profile picture uploads from the app

Expo's fetch rejects React Native's { uri, name, type } FormData parts ("Unsupported FormDataPart
implementation"), so every upload failed. Upload an expo-file-system File instead, shrunk to 1024 px
first. The server also takes bigger photos (25 MB, sharp's default pixel limit) and logs why a
picture couldn't be read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011Y2iUsKEWDuRGjK5FPmcUP
This commit is contained in:
2026-10-15 13:20:12 -04:00
co-authored by Claude Opus 5.5
parent b705bfcce4
commit 31aed8dec4
6 changed files with 49 additions and 10 deletions
+14 -4
View File
@@ -1,3 +1,5 @@
import { File } from 'expo-file-system';
import { ImageManipulator, SaveFormat } from 'expo-image-manipulator';
import * as ImagePicker from 'expo-image-picker';
import { router } from 'expo-router';
import { useState } from 'react';
@@ -103,10 +105,18 @@ function AvatarPicker() {
});
const asset = result.canceled ? null : result.assets[0];
if (!asset) return;
const form = new FormData();
// React Native's FormData takes a file as { uri, name, type }.
form.append('file', { uri: asset.uri, name: asset.fileName ?? 'avatar.jpg', type: asset.mimeType ?? 'image/jpeg' } as unknown as Blob);
run(() => api.uploadAvatar(form));
run(async () => {
// Shrink first: photos from 50-200 MP cameras are huge, and the server keeps 512 px anyway.
const side = Math.min(1024, asset.width || 1024);
const image = await (await ImageManipulator.manipulate(asset.uri).resize({ width: side }).renderAsync()).saveAsync({
compress: 0.85,
format: SaveFormat.JPEG,
});
const form = new FormData();
// Expo's fetch needs a real file object (it rejects React Native's { uri, name, type } parts).
form.append('file', new File(image.uri) as unknown as Blob);
return api.uploadAvatar(form);
});
};
const remove = () =>