Extending Upload to have nested folders #1961
Replies: 18 comments 12 replies
-
Yes this would indeed be very nice feature to have. I'm in need of oraganizing the files to folders scoped to collection item. So when a Page is deleted I could just iterate the filenames in folder |
Beta Was this translation helpful? Give feedback.
-
Would also really appreciate is this became a feature, right now I have way too many media files which I'm not able to view in an organised manner. |
Beta Was this translation helpful? Give feedback.
-
Looking for this feature |
Beta Was this translation helpful? Give feedback.
-
Has anybody found a workaround for this feature? Would be nice to have for sure. |
Beta Was this translation helpful? Give feedback.
-
Yeah, Only way to do it to give up and try to save all your files into S3. You can freely define your path as you want. I also have so so many images, saving all of them into ONE media folder is too silly and not logically organised as well. I've spent a whole day to look into it, but failed. |
Beta Was this translation helpful? Give feedback.
-
Any progress on this feature? This should be a priority 1 feature. |
Beta Was this translation helpful? Give feedback.
-
I create a work-around...
if (!fs.existsSync(mediaDir + '/' + catId)) { |
Beta Was this translation helpful? Give feedback.
-
so, I've been searching for a while how can I do it natively, nothing yet? |
Beta Was this translation helpful? Give feedback.
-
It'd be great to have this feature supported natively |
Beta Was this translation helpful? Give feedback.
-
I think this might overlap with: #5664 |
Beta Was this translation helpful? Give feedback.
-
Update on this? |
Beta Was this translation helpful? Give feedback.
-
I switched back to Strapi because of this issue. In my case, I have million of images (thumbnail, medium, large...), it is really slow if putting a large number of images in a single directory. |
Beta Was this translation helpful? Give feedback.
-
I developed 2 applications on Payload but this was the reason that I switched to Strapi. |
Beta Was this translation helpful? Give feedback.
-
@jmikrut, would really appreciate if this was launched soon |
Beta Was this translation helpful? Give feedback.
-
any updates of this ? |
Beta Was this translation helpful? Give feedback.
-
I'm sad this hasn't been addressed yet |
Beta Was this translation helpful? Give feedback.
-
I also tried to find a solution to this problem because I was interested in using this product. However, despite my searches, I have not been able to find an easy way to solve it. After studying the source code, I was disappointed and realized that a quick solution was not possible. However, I can offer at least some kind of solution that is not ideal, but is capable of completing the task. Perhaps in the future I will be able to improve it or even create a plugin. SourcesCreate collections with hooksImportant: the collection is called 'Images' ! export const Images: CollectionConfig = {
slug: 'images',
access: {
read: () => true,
},
fields: [
{
name: 'alt',
type: 'text',
required: true,
},
],
hooks: {
beforeOperation: [
({ req, operation }) => {
if ((operation === 'create' || operation === 'update') && req.file) {
if (req.file) {
const file = req.file as unknown as { md5: string }
const hash = file.md5
req.file.name = `${hash.slice(0, 2)}_${hash.slice(2, 4)}_${req.file.name}`
console.log(req.file)
}
}
},
],
afterChange: [
({ collection, doc }) => {
function move(dir: string, filename: string) {
const oldPath = path.resolve(dir, filename)
const matches = [...filename.matchAll(/^([^_]*)_([^_]*)_(.*)$/gm)][0]
const newFolder = path.resolve(dir, matches[1], matches[2])
const newPath = path.resolve(newFolder, matches[3])
mkdirSync(newFolder, {
recursive: true,
})
renameSync(oldPath, newPath)
}
if (collection.upload.staticDir) {
move(collection.upload.staticDir, doc.filename)
const sizes = doc.sizes as Record<string, { filename: string }>
Object.values(sizes).forEach((item) => {
move(collection.upload.staticDir ?? '', item.filename)
})
}
},
],
afterDelete: [
({ doc, collection }) => {
function del(dir: string, filename: string) {
const matches = [...filename.matchAll(/^([^_]*)_([^_]*)_(.*)$/gm)][0]
const newFolder = path.resolve(dir, matches[1], matches[2])
rmSync(path.resolve(newFolder, matches[3]), { force: true })
}
if (collection.upload.staticDir) {
del(collection.upload.staticDir, doc.filename)
const sizes = doc.sizes as Record<string, { filename: string }>
Object.values(sizes).forEach((item) => {
del(collection.upload.staticDir ?? '', item.filename)
})
}
},
],
},
upload: {
staticDir: uploadImagesFolder,
adminThumbnail: '384',
mimeTypes: ['image/jpeg', 'image/png', 'image/webp'],
formatOptions: {
format: 'webp',
options: { quality: 85 },
},
imageSizes: [
...
],
},
} Create custom routecreate file in app/api/{images - collection name}/file/[slug]/route.ts import { uploadImagesFolder } from '@/collections/Images'
import { stat, readFile } from 'fs/promises'
import path from 'path'
function changePath(dir: string, filename: string) {
const matches = [...filename.matchAll(/^([^_]*)_([^_]*)_(.*)$/gm)][0]
const newPath = path.resolve(dir, matches[1], matches[2], matches[3])
return newPath
}
export async function GET(_: Request, { params }: { params: Promise<{ slug: string }> }) {
const slug = (await params).slug
const filePath = changePath(uploadImagesFolder, slug)
const stats = await stat(filePath)
const headers = new Headers()
headers.set('Content-Type', 'image/webp')
headers.set('Content-Length', stats.size + '')
const data = await readFile(filePath)
return new Response(data, {
headers,
status: 200,
})
} |
Beta Was this translation helpful? Give feedback.
-
Why is there a screenshot of the landing page showing a Folder functionality for the Media if this is no where available ? |
Beta Was this translation helpful? Give feedback.
-
I have a media collection which I use to save all media files. I want to organize the files into subfolders. Currently, all files are saved in folder: media
How can I save files from collection-1 to media/collection-1 when using media relationship.
Strapi provides media gallery out of the box in which you can create folders to structure your media gallery such as media/products or media/posts. Maybe we can define the folder inside the relationship such as below.
{ name: 'products', type: 'upload', relationTo: 'media', DESTINATION_FOLDER: '../../media/products' // Example },
Beta Was this translation helpful? Give feedback.
All reactions