diff --git a/packages/payload/src/admin/components/elements/PreviewSizes/index.tsx b/packages/payload/src/admin/components/elements/PreviewSizes/index.tsx index 5de865f78d..0dc79dd8c6 100644 --- a/packages/payload/src/admin/components/elements/PreviewSizes/index.tsx +++ b/packages/payload/src/admin/components/elements/PreviewSizes/index.tsx @@ -78,16 +78,17 @@ const PreviewSizes: React.FC<{ const [orderedSizes, setOrderedSizes] = useState(() => sortSizes(sizes, imageSizes)) const [selectedSize, setSelectedSize] = useState(null) - const generateImageUrl = (filename) => { - return `${staticURL}/${filename}${imageCacheTag ? `?${imageCacheTag}` : ''}` + const generateImageUrl = (doc) => { + if (!doc.filename) return null + if (doc.url) return `${doc.url}${imageCacheTag ? `?${imageCacheTag}` : ''}` } useEffect(() => { setOrderedSizes(sortSizes(sizes, imageSizes)) }, [sizes, imageSizes, imageCacheTag]) const mainPreviewSrc = selectedSize - ? generateImageUrl(`${orderedSizes[selectedSize]?.filename}`) - : generateImageUrl(doc.filename) + ? generateImageUrl(doc.sizes[selectedSize]) + : generateImageUrl(doc) const originalImage = useMemo( (): FileSizes[0] => ({ @@ -121,12 +122,12 @@ const PreviewSizes: React.FC<{ meta={originalImage} name={originalFilename} onClick={() => setSelectedSize(null)} - previewSrc={generateImageUrl(doc.filename)} + previewSrc={generateImageUrl(doc)} /> {Object.entries(orderedSizes).map(([key, val]) => { const selected = selectedSize === key - const previewSrc = val.filename ? generateImageUrl(val.filename) : undefined + const previewSrc = generateImageUrl(val) if (previewSrc) { return ( diff --git a/packages/payload/src/uploads/generateFileData.ts b/packages/payload/src/uploads/generateFileData.ts index 40bfc41269..cc3718768a 100644 --- a/packages/payload/src/uploads/generateFileData.ts +++ b/packages/payload/src/uploads/generateFileData.ts @@ -17,6 +17,7 @@ import { FileUploadError, MissingFile } from '../errors' import canResizeImage from './canResizeImage' import cropImage from './cropImage' import getFileByPath from './getFileByPath' +import getFileByURL from './getFileByURL' import getImageSize from './getImageSize' import getSafeFileName from './getSafeFilename' import resizeAndTransformImageSizes from './imageResizer' @@ -63,12 +64,22 @@ export const generateFileData = async ({ } if (!file && uploadEdits && data) { - const { filename } = data as FileData - const filePath = `${staticPath}/${filename}` - const response = await getFileByPath(filePath) + const { filename, url } = data as FileData - overwriteExistingFiles = true - file = response as UploadedFile + try { + if (url && url.startsWith('/')) { + const filePath = `${staticPath}/${filename}` + const response = await getFileByPath(filePath) + file = response as UploadedFile + overwriteExistingFiles = true + } else { + const response = await getFileByURL(url) + file = response as UploadedFile + overwriteExistingFiles = true + } + } catch (err) { + throw new FileUploadError(req.t) + } } if (!file) { @@ -190,7 +201,12 @@ export const generateFileData = async ({ fileData.width = info.width fileData.height = info.height fileData.filesize = info.size - req.files.file = fileForResize + + if (file.tempFilePath) { + await fs.promises.writeFile(file.tempFilePath, croppedImage) // write fileBuffer to the temp path + } else { + req.files.file = fileForResize + } } else { filesToSave.push({ buffer: fileBuffer?.data || file.data, diff --git a/packages/payload/src/uploads/getBaseFields.ts b/packages/payload/src/uploads/getBaseFields.ts index 7ef1209192..f22e33ffda 100644 --- a/packages/payload/src/uploads/getBaseFields.ts +++ b/packages/payload/src/uploads/getBaseFields.ts @@ -142,7 +142,7 @@ const getBaseUploadFields = ({ collection, config }: Options): Field[] => { return `${uploadOptions.staticURL}/${sizeFilename}` } - return undefined + return null }, ], }, diff --git a/packages/payload/src/uploads/getFileByURL.ts b/packages/payload/src/uploads/getFileByURL.ts new file mode 100644 index 0000000000..9045a62ec6 --- /dev/null +++ b/packages/payload/src/uploads/getFileByURL.ts @@ -0,0 +1,26 @@ +import fetch from 'node-fetch' +import path from 'path' + +import type { File } from './types' + +const getFileByURL = async (url: string): Promise => { + if (typeof url === 'string') { + const res = await fetch(url, { + headers: { + 'Content-Type': 'application/json', + }, + method: 'GET', + }) + const data = await res.buffer() + const name = path.basename(url) + + return { + name, + data, + mimetype: res.headers.get('content-type') || undefined, + size: Number(res.headers.get('content-length')) || 0, + } + } +} + +export default getFileByURL diff --git a/packages/payload/src/uploads/types.ts b/packages/payload/src/uploads/types.ts index dddadae900..0b8a51d0bd 100644 --- a/packages/payload/src/uploads/types.ts +++ b/packages/payload/src/uploads/types.ts @@ -22,6 +22,7 @@ export type FileData = { mimeType: string sizes: FileSizes tempFilePath?: string + url?: string width: number } diff --git a/test/plugin-cloud/collections/Media.ts b/test/plugin-cloud/collections/Media.ts index b7ada794c8..e38a6f45a3 100644 --- a/test/plugin-cloud/collections/Media.ts +++ b/test/plugin-cloud/collections/Media.ts @@ -2,7 +2,12 @@ import type { CollectionConfig } from '../../../packages/payload/src/collections export const Media: CollectionConfig = { slug: 'media', + access: { + read: () => true, + create: () => true, + }, upload: { + staticURL: process.env.PAYLOAD_PUBLIC_SERVER_URL, imageSizes: [ { height: 400, diff --git a/test/plugin-cloud/config.ts b/test/plugin-cloud/config.ts index 759fa384eb..a5e0abb7a8 100644 --- a/test/plugin-cloud/config.ts +++ b/test/plugin-cloud/config.ts @@ -14,6 +14,7 @@ dotenv.config({ export default buildConfigWithDefaults({ collections: [Media, Users], + serverURL: process.env.PAYLOAD_PUBLIC_SERVER_URL, admin: { webpack: (config) => ({ ...config,