I’m encountering an issue when uploading images to Supabase storage. After uploading the images and updating the database with the new photo URLs, I attempt to display them immediately. However, I receive a status 400 error (GET method). Interestingly, the URLs work when checked separately, and images uploaded earlier are displayed properly. The issue only arises with newly uploaded photos.
Here is my code for context:
const handleFormSubmit = async (
values: Artist,
setSubmitting: SetSubmitting
) => {
setSubmitting(true)
// Filter images to don't upload images that are going to be deleted and vice versa
const {
itemsToUploadClone: imagesToUploadClone,
itemsToDeleteClone: imagesToDeleteClone,
} = filterItems(imagesToUpload, imagesToDelete)
try {
// Perform image upload and deletion in parallel
await Promise.all([
imagesToUploadClone.length > 0
? uploadImages(imagesToUploadClone, values.imgList)
: Promise.resolve(),
imagesToDeleteClone.length > 0
? deleteArtistImages(imagesToDeleteClone)
: Promise.resolve(),
])
const success = await apiUpdateArtist(values)
if (success) {
navigate('/artists/details/' + values.id)
popNotification(t('artists.artistUpdated'))
}
} catch (error) {
console.error(
'Error in processing images or updating artist: ',
error
)
} finally {
setSubmitting(false)
}
}
Here is the code with image transformations and upload to supabase:
const uploadImages = async (
imagesToUpload: Image[],
formImages: Image[]
) => {
await Promise.all(
imagesToUpload.map(async (imageToUpload) => {
try {
const formImage = formImages.find(
(img) => img.id === imageToUpload.id
) as Image
const rawFile = await getFileFromBlobUrl(
imageToUpload.rawFilePath,
imageToUpload.fileName
)
// resize image to 3 different sizes and upload them to supabase storage
const resizeOptions: ResizeOption[] = [
{
maxWidth: 144,
maxHeight: 144,
format: 'WEBP',
quality: 75,
minWidth: 144,
minHeight: 144,
},
{
maxWidth: 760,
maxHeight: 760,
format: 'JPEG',
quality: 90,
minWidth: 480,
minHeight: 480,
},
{
maxWidth: 2000,
maxHeight: 2000,
format: 'JPEG',
quality: 90,
},
]
try {
const resizePromises = resizeFile(
rawFile,
resizeOptions
)
let resizedImages = await Promise.all(resizePromises)
resizedImages = [...resizedImages, rawFile]
const sizes = [
'small',
'medium',
'large',
'raw',
] as const
resizedImages.forEach(async (resizedImage, index) => {
const filePath = `/img/artist/${artistData.id}/${
sizes[index]
}/${imageToUpload.id}.${resizedImage.type
.split('/')[1]
.toLowerCase()}`
await supabase.storage.from('general').upload(filePath, resizedImage)
})
const imageBaseUrl = `${
import.meta.env.VITE_SUPABASE_STORAGE_URL
}/img/artist/${artistData.id}`
formImage.smallFilePath = `${imageBaseUrl}/small/${
imageToUpload.id
}.${resizedImages[0].type.split('/')[1]}`
formImage.mediumFilePath = `${imageBaseUrl}/medium/${
imageToUpload.id
}.${resizedImages[1].type.split('/')[1]}`
formImage.largeFilePath = `${imageBaseUrl}/large/${
imageToUpload.id
}.${resizedImages[2].type.split('/')[1]}`
formImage.rawFilePath = `${imageBaseUrl}/raw/${
imageToUpload.id
}.${resizedImages[3].type.split('/')[1]}`
} catch (error) {
console.error('Error resizing images:', error)
}
} catch (error) {
console.error('Error uploading image: ', error)
}
})
)
}
The following code refers to the request for an image from the storage (image url):
{imgList.map((img) => (
<SortableItem key={img.id} id={img.id}>
<div
key={img.id}
className="group relative rounded border p-2 flex justify-center touch-pan-x aspect-square"
>
<img
className="rounded object-contain"
src={img.smallFilePath}
alt={img.fileName}
/>
<div className="absolute inset-2 bg-gray-900/[.7] group-hover:flex hidden text-xl items-center justify-center">
<span
className="text-gray-100 hover:text-gray-300 cursor-pointer p-1.5"
onClick={() => onViewOpen(img)}
>
<HiEye />
</span>
<span
className="text-gray-100 hover:text-gray-300 cursor-pointer p-1.5"
onClick={() => onDeleteConfirmation(img)}
>
<HiTrash />
</span>
</div>
</div>
</SortableItem>
))}
Here are also the request header screenshots (same image, but one after refreshing the page):
status 400 status 200
To troubleshoot, I added a 1-second timeout before displaying the site with images, which resulted in all images being displayed properly. Additionally, if I initially receive an error and then refresh the page, the images display as expected. I’ve also tried implementing a custom function that checks image availability in an interval loop, but I believe there should be a more appropriate solution. I expected the images to display immediately after uploading without the need for these workarounds.