Strapi CMS is a popular, open-source headless CMS that provides a flexible and easy-to-use platform for building web applications. One of its core plugins is the upload provider, but the default implementation ships with some biased configurations that can lead to trouble.
In this article, I’ll show you a simple method for overriding the default formatFileInfo method in Strapi to stop it from automatically changing and adding a hash to uploaded filenames.
The Problem
In some cases, we want to preserve the original filename of an uploaded file/object. By default, Strapi will change it using the following method in its source code:
const generateFileName = (name) => {
const baseName = nameToSlug(name, { separator: '_', lowercase: false });
return `${baseName}_${randomSuffix()}`;
};
The Solution
To resolve this issue, we need to override the default formatFileInfo method, which leverages the generateFileName function.
Overriding a plugin method
- Open the
src/index.js
file in your project and add the following code inside the register method. What we’re doing is swapping out the plugin’s service method with our own. Note that this will work for any method or function available on the global strapi object.
// src/index.js
module.exports = {
register({ strapi }) {
// Override the default upload info formatter with custom function.
strapi.services["plugin::upload.upload"].formatFileInfo =
require("./extensions/upload/overrides").formatFileInfoOverride;
},
}
2. Create a file in src/extensions/upload/overrides.js
to store the override function. Add the following code to that file, which is a slightly refactored version of the original formatFileInfo method:
const _ = require("lodash");
const path = require("path");
const { extension } = require("mime-types");
/**
* Overriding formatFileInfo function for upload plugin to
* maintain original file naming.
*/
export async function formatFileInfoOverride(
{ filename, type, size },
fileInfo = {},
metas = {}
) {
const fileService = strapi.plugin("upload").service("file");
let ext = path.extname(filename);
if (!ext) {
ext = `.${extension(type)}`;
}
const usedName = (fileInfo.name || filename).normalize();
const basename = path.basename(usedName, ext);
const entity = {
ext,
mime: type,
hash: basename,
name: usedName,
folder: fileInfo.folder,
caption: fileInfo.caption,
alternativeText: fileInfo.alternativeText,
size: Math.round((size / 1000) * 100) / 100,
folderPath: await fileService.getFolderPath(fileInfo.folder),
};
const { refId, ref, field } = metas;
if (refId && ref && field) {
entity.related = [{
id: refId,
__type: ref,
__pivot: { field },
}];
}
if (metas.path) {
entity.path = metas.path;
}
if (metas.tmpWorkingDirectory) {
entity.tmpWorkingDirectory = metas.tmpWorkingDirectory;
}
return entity;
}
Closing thoughts
This solution works for me, and I hope it helps others facing a similar issue. While working with Strapi, I find it a bit in-flexible when handling files. However, with this solution, I overcame this limitation and got the needed functionality.
Give it a try, and if you have any questions, feel free to ask!