在我最近的一个项目中,我正在研究这个非常酷的事情,称为订单管理系统(OMS)。基本上,正是这个集中式平台可以帮助非政府组织自动化各种东西 - 例如管理他们的程序,应用程序,员工,学生,志愿者,电子邮件,文件和表格。
无论如何,在项目的某个时刻,我必须弄清楚如何处理特定端点的文件上传到云。我的最初解决方案奏效了,但是有点慢 - 一次上传五个文件大约需要一段时间。作为开发人员,我知道我可以做得更好,所以我想出了一个新的解决方案,该解决方案更快地工作。
如果您正在使用Multer,这是一个非常方便的工具,用于在Node.js中上传文件,则可以使用它将文件上传到Cloudinary:
import cloudinary from "./cloudinary";
const { upload } = cloudinary.uploader;
const uploadFile = async (file: Express.Multer.File) => {
const uploadedFile = await upload(file.path, {
folder: "/upload-folder/files",
public_id: file.fieldname,
overwrite: true,
});
return uploadedFile.secure_url;
};
上传文件后,您可以将结果保存在数据库中。为此,请使用文件的字段名称(例如“ profileImage”)作为键,而secure_url作为值。
但是,有时您可能需要一次上传多个文件。例如,如果您在页面上有三个文件上传输入,并且其中一个可以让用户上传最多三个文件,则必须处理总共五个文件。在这种情况下,您可以使用输入的名称属性来识别哪个文件属于。因此,如果用于上传三个文件的输入命名为“ supportingDocuments”,其他两个输入命名为“ profileImage”和“简历”,则可以使用这些名称来跟踪哪些文件已上传到位置。
。以上提到的三个文件输入,这是req.files
的外观示例:
[
{
"fieldname": "supportingDocuments",
"originalname": "document1.pdf",
"encoding": "7bit",
"mimetype": "application/pdf",
"size": 1234567,
"buffer": "<Buffer 25 50 44 46 2d 31 2e 33 ... >"
},
{
"fieldname": "supportingDocuments",
"originalname": "document2.jpg",
"encoding": "7bit",
"mimetype": "image/jpeg",
"size": 345678,
"buffer": "<Buffer ff d8 ff e0 00 10 ... >"
},
{
"fieldname": "supportingDocuments",
"originalname": "document3.docx",
"encoding": "7bit",
"mimetype": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"size": 987654,
"buffer": "<Buffer 50 4b 03 04 0a 00 ... >"
},
{
"fieldname": "profileImage",
"originalname": "profile.jpg",
"encoding": "7bit",
"mimetype": "image/jpeg",
"size": 234567,
"buffer": "<Buffer ff d8 ff e0 00 10 ... >"
},
{
"fieldname": "resume",
"originalname": "resume.pdf",
"encoding": "7bit",
"mimetype": "application/pdf",
"size": 876543,
"buffer": "<Buffer 25 50 44 46 2d 31 2e 33 ... >"
}
]
因此,如果我们在“ supportingDocuments”字段中上传了三个文件,并且在“ profileImage”和“ recume”字段中每个文件中每个文件,我们如何上传这些文件并将结果保存在数据库中?
这是:
import { UploadApiResponse } from "cloudinary";
import cloudinary from "./cloudinary";
type Files =
| Express.Multer.File[]
| { [fieldname: string]: Express.Multer.File[] };
async function uploadFiles(
files: Files
): Promise<{ [key: string]: string | string[] }> {
if (!Array.isArray(files)) return {};
const results: { [key: string]: string | string[] } = {};
const fieldNames: string[] = [];
const fieldNamesOccurrences: { [fieldname: string]: number } = {};
const uploads = files.map((file, i) => {
fieldNames.push(file.fieldname);
return cloudinary.uploader.upload(file.path, {
folder: "/upload-folder/files",
public_id: file.fieldname + i,
overwrite: true,
});
});
const uploadResults: UploadApiResponse[] = await Promise.all(uploads);
for (let i = 0; i < fieldNames.length; i++) {
const fieldName = fieldNames[i];
const uploadedFile = uploadResults[i];
fieldNamesOccurrences[fieldName] =
(fieldNamesOccurrences[fieldName] || 0) + 1;
if (fieldNamesOccurrences[fieldName] > 1) {
if (Array.isArray(results[fieldName])) {
(results[fieldName] as Array<string>).push(uploadedFile.secure_url);
} else if (typeof results[fieldName] === "string") {
results[fieldName] = [
results[fieldName] as string,
uploadedFile.secure_url,
];
} else {
results[fieldName] = uploadedFile.secure_url;
}
} else {
results[fieldName] = uploadedFile.secure_url;
}
}
return results;
}
因此,首先,我们需要给uploadFiles
函数一个称为文件的参数。 (来自req.files
)。这可以是文件数组,也可以是具有字段名称和文件数组的对象。我们在函数中检查一下。
接下来,我们创建一些空的对象和数组,以帮助我们跟踪所有内容。我们有一个称为results
的空对象,一个称为fieldNames
的空数组,另一个称为fieldNamesOccurrences
的空对象。
然后,对于“文件数组”中的每个文件,我们获得了与之关联的字段的名称,并将其添加到fieldNames
数组中。我们还使用Cloudinary软件包上传每个文件,然后将上传的承诺推到一个名为uploads
的数组。
我们使用一种称为Promise.all()的特殊方法来等待所有文件上传立即完成。这使得过程更快!上传所有文件后,我们将获得一系列uploadapiresponse对象,称为uploadResults
。
最后,我们循环浏览fieldNames
数组,并检查每个字段名称出现多少次。如果看起来不止一次,我们将上传的文件URL添加到与该字段名称关联的结果对象中的数组中。如果仅出现一次,我们简单地将URL设置为与结果对象中该字段名称关联的字符串。
就是这样! uploadFiles
函数可帮助您使用Cloudinary上传文件,并返回一个对象,向您显示与每个字段名称关联的上传文件的URL。
真棒新闻对吗?从功能中获得结果后,您可以根据需要将它们保存在数据库中。这意味着您可以上传到Cloudinary并将文件保存在数据库超快中。
这就是所有人ð。喜欢并在评论部分留下您的想法。随时在Twitter上关注我。