fix: Profilbild-Upload auf JSON/Base64 umgestellt statt multipart
POST /profile/avatar schlug live mit net::ERR_FAILED fehl (Verbindung abgebrochen, keine Antwort) - selbst bei einer winzigen Testdatei. CORS-Preflight lief sauber durch, nur der eigentliche multipart-POST nicht; passt zum bereits dokumentierten Cloudflare-Verhalten bei multipart-Uploads (siehe .gitea/workflows/*-image.yml). Umgangen durch Umstellung auf denselben JSON-Content-Type, der fuer alle anderen Endpunkte nachweislich zuverlaessig funktioniert: Bild wird clientseitig als data:-URL kodiert und im JSON-Body gesendet. Globales JSON-Body-Limit auf 5mb angehoben (deckt 2MB-Bild plus Base64-Overhead).
This commit is contained in:
1 parent
abe1f6e8cf
commit
135738fdfc
7 files changed
+81
-49
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { apiFetch, apiFetchBlob, apiFetchFormData } from "@/lib/auth/api-client";
|
||||
import { apiFetch, apiFetchBlob } from "@/lib/auth/api-client";
|
||||
import { MfaEnrollment, ProfileSummary, UpdateProfileInput } from "./types";
|
||||
|
||||
export function updateProfile(input: UpdateProfileInput): Promise<ProfileSummary> {
|
||||
@@ -22,10 +22,26 @@ export function deactivateAccount(currentPassword: string): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
export function uploadAvatar(file: File): Promise<void> {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
return apiFetchFormData<void>("/profile/avatar", formData);
|
||||
// Sent as a base64 data: URL in a plain JSON body rather than
|
||||
// multipart/form-data: this deployment's Cloudflare proxy has a known
|
||||
// history of mishandling multipart uploads regardless of size (see the
|
||||
// registry-push workaround in .gitea/workflows/*-image.yml), while plain
|
||||
// JSON POSTs to this same backend have been reliable all along.
|
||||
function fileToDataUrl(file: File): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => resolve(String(reader.result));
|
||||
reader.onerror = () => reject(reader.error);
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
|
||||
export async function uploadAvatar(file: File): Promise<void> {
|
||||
const data = await fileToDataUrl(file);
|
||||
return apiFetch<void>("/profile/avatar", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ data }),
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteAvatar(): Promise<void> {
|
||||
|
||||
Reference in new issue
Block a user