We need to create a folder for each user and store their files within it. Is it possible to do it in strapi v4 using media uploads

[details=“System Information”]

  • Strapi Version: 4
  • Operating System: windows 10
  • Database: mysql
  • Node Version: v16.16.0
  • NPM Version: 8.11.0
  • Yarn Version: 1.22.15
    [/details] As the upload media folder becomes very cluttered is there a way to create folders in upload and group the media files.

2 Likes

Well, folders are a thing in the media library provided by the upload plugin since I think v4.3.0:

I’m sure you can create and access folders with a custom controller.

1 Like

Thank you so much.
But how can I do this through an API.
Can I create a new folder using API and then upload the files into that folder

I solved this way, on my case, on top of the user level folder, I have a category folder, lets call it firstLevelFolder

example.file from user_123 would end up on

/firstLevelFolder/user_123/example.file

const uploadUserFilesService = async (fileArray, user) => {
  const uploadService = strapi.plugins.upload.services.upload;
  const folderService = strapi.plugins.upload.services.folder;

  // FIRST LEVEL FOLDER BLOCK
  let firstLevelFolderBase = await strapi.query('plugin::upload.folder').findOne({where: {name: 'firstLevelFolder'}});
  if (!firstLevelFolderBase) {
    await folderService.create({name: 'firstLevelFolder'})
    firstLevelFolderBase = await strapi.query('plugin::upload.folder').findOne({where: {name: 'firstLevelFolder'}});
  }

// USER LEVEL FOLDER BLOCK
  let userLevelFolder = await strapi.query('plugin::upload.folder').findOne({where: {name: user.username, parent: firstLevelFolderBase}});
  if (!userLevelFolder) {
    await folderService.create({name: user.username, parent: firstLevelFolderBase.id})
    userLevelFolder = await strapi.query('plugin::upload.folder').findOne({where: {name: user.username, parent: firstLevelFolderBase}});
  }


  // NOW LETS UPDATE THE FILES
  const uploadedFiles = await Promise.map(fileArray, async (file) => {
      return uploadService.upload({
        data: {
          path: `firstLevelFolder/${user.username}`,
          fileInfo: {folder: userLevelFolder.id},
        },
        files: file
      })
    }
  );
}
5 Likes

Thank you i will try this

I have created folders using the API(strapi.plugins.upload.services.folder) but how do i upload files to this folders

As per my understanding i can use the api/document to upload files to media library however i need to upload files to the newly created folder inside the media library.

Any updates please?

any updates??

You need to add the folder id and path on your entity, like this:

const usersFolder = await /*...*/;
const userFolder = await /*...*/;

const entity = {
    name: 'profile-picture',
    path: `${usersFolder.name}/${userFolder.name}`, // Only available on AWS S3
    folder: userFolder.id, // Parent folder ID
    folderPath: userFolder.path, // Parent folder path
    ext: path.extname(file.filename),
    mime: file.mimetype,
    provider: uploadConfig.provider,
    getStream() {
         return Readable.from(readStream);
    },
};

await uploadService.upload(entity);

const res = await strapi.query('plugin::upload.file').create({
    data: entity,
});

I hope it helps

3 Likes

No meu caso eu preciso fazer upload do arquivo pra pasta /2/3/4/5 porém já tentei mandar pra api o folder e o folderPath como no seu exemplo e não deu certo. Já tentei também mandar com um fileInfo:{“name”:“file.txt”,“foler”:5} no formData mas não funcionou. No S3 ele monta o caminho correto com o path, mas no strapi continua salvando na pasta genérica API Uploads.
Você consegue me ajudar?

Do you have it on Typescript?

My understanding is that it’s not just about creating folder views logically, there should also be a load balancing storage solution on the disk instead of uploading all files to one disk folder。
Storing a large number of files in the ’uploads‘ folder can have performance bottlenecks!