Harden client uploads and add storage fallback
Validate presigned upload responses and fall back to Vercel Blob when third-party storage upload fails so photo uploads remain available. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
d5001c9ee5
commit
053a3b4acc
@ -119,11 +119,27 @@ export const uploadFromClientViaPresignedUrl = async (
|
||||
file: File | Blob,
|
||||
fileName: string,
|
||||
) => {
|
||||
const url = await fetch(`${PATH_API_PRESIGNED_URL}/${fileName}`)
|
||||
.then((response) => response.text());
|
||||
const response = await fetch(`${PATH_API_PRESIGNED_URL}/${fileName}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to get presigned URL: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
return fetch(url, { method: 'PUT', body: file })
|
||||
.then(() => `${baseUrlForStorage(CURRENT_STORAGE)}/${fileName}`);
|
||||
const url = (await response.text()).trim();
|
||||
|
||||
if (!/^https?:\/\//i.test(url)) {
|
||||
throw new Error('Invalid presigned URL response');
|
||||
}
|
||||
|
||||
const uploadResponse = await fetch(url, { method: 'PUT', body: file });
|
||||
if (!uploadResponse.ok) {
|
||||
throw new Error(
|
||||
`Failed to upload with presigned URL: ${uploadResponse.status} ${uploadResponse.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
return `${baseUrlForStorage(CURRENT_STORAGE)}/${fileName}`;
|
||||
};
|
||||
|
||||
export const uploadFileFromClient = async (
|
||||
@ -136,13 +152,24 @@ export const uploadFileFromClient = async (
|
||||
? `${_fileName}-${generateStorageId()}.${extension}`
|
||||
: `${_fileName}.${extension}`;
|
||||
|
||||
return (
|
||||
if (
|
||||
CURRENT_STORAGE === 'cloudflare-r2' ||
|
||||
CURRENT_STORAGE === 'aws-s3' ||
|
||||
CURRENT_STORAGE === 'minio'
|
||||
)
|
||||
? uploadFromClientViaPresignedUrl(file, fileName)
|
||||
: vercelBlobUploadFromClient(file, fileName);
|
||||
) {
|
||||
try {
|
||||
return await uploadFromClientViaPresignedUrl(file, fileName);
|
||||
} catch (error) {
|
||||
// Fall back to Vercel Blob when configured, so uploads stay available
|
||||
// even if third-party object storage is temporarily unreachable.
|
||||
if (HAS_VERCEL_BLOB_STORAGE) {
|
||||
return vercelBlobUploadFromClient(file, fileName);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return vercelBlobUploadFromClient(file, fileName);
|
||||
};
|
||||
|
||||
export const putFile = (
|
||||
|
||||
Loading…
Reference in New Issue
Block a user