Files
payload/packages/plugin-cloud-storage/src/client/createClientUploadHandler.tsx
Sasha fc42c40883 fix(storage-s3, storage-azure, storage-gcs): client uploads when a collection has prefix configured (#11436)
### What?
Fixes client uploads when storage collection config has the `prefix`
property configured. Previously, it failed with "Object key was not
found".

### Why?
This is expected to work.

### How?
The client upload handler now receives to its props `prefix`. Then it
threads it to the server-side `staticHandler` through
`clientUploadContext` and then to `getFilePrefix`, which checks for
`clientUploadContext.prefix` and returns if there is.

Previously, `staticHandler` tried to load the file without including
prefix consideration.

This changes only these adapters:
* S3
* Azure
* GCS

With the Vercel Blob adapter, `prefix` works correctly.
2025-02-28 15:50:23 -05:00

74 lines
1.6 KiB
TypeScript

'use client'
import type { UploadCollectionSlug } from 'payload'
import { useConfig, useEffectEvent, useUploadHandlers } from '@payloadcms/ui'
import { Fragment, type ReactNode, useEffect } from 'react'
type ClientUploadHandlerProps<T extends Record<string, unknown>> = {
children: ReactNode
collectionSlug: UploadCollectionSlug
enabled?: boolean
extra: T
prefix?: string
serverHandlerPath: string
}
export const createClientUploadHandler = <T extends Record<string, unknown>>({
handler,
}: {
handler: (args: {
apiRoute: string
collectionSlug: UploadCollectionSlug
extra: T
file: File
prefix?: string
serverHandlerPath: string
serverURL: string
updateFilename: (value: string) => void
}) => Promise<unknown>
}) => {
return function ClientUploadHandler({
children,
collectionSlug,
enabled,
extra,
prefix,
serverHandlerPath,
}: ClientUploadHandlerProps<T>) {
const { setUploadHandler } = useUploadHandlers()
const {
config: {
routes: { api: apiRoute },
serverURL,
},
} = useConfig()
const initializeHandler = useEffectEvent(() => {
if (enabled) {
setUploadHandler({
collectionSlug,
handler: ({ file, updateFilename }) => {
return handler({
apiRoute,
collectionSlug,
extra,
file,
prefix,
serverHandlerPath,
serverURL,
updateFilename,
})
},
})
}
})
useEffect(() => {
initializeHandler()
}, [])
return <Fragment>{children}</Fragment>
}
}