[英]multi file upload with skipper-better-s3 and sailjs returns the same key
As seen in the title, I am currently using sailjs
+ skipper-better-s3
for s3 upload.如标题所示,我目前使用sailjs
+ skipper-better-s3
进行s3 上传。 Started with uploading one file which works great, then because change request the need of multi-file upload at once so I added a for
loop but by doing this, all keys will be the same and ended up the only one file is uploaded which is the last uploaded file but with the first upload filename.从上传一个效果很好的文件开始,然后因为更改请求需要一次上传多文件,所以我添加了一个for
循环,但是通过这样做,所有的键都将是相同的,最后只上传了一个文件,即最后上传的文件,但使用第一个上传文件名。
I did read some articles and people are saying something like The problem is because for loop is synchronous and file upload is asynchronous
and people saying the result of this is using a recursion which I tried too but no luck though, the same thing happens.我确实阅读了一些文章,人们说类似The problem is because for loop is synchronous and file upload is asynchronous
,人们说这样做的结果是使用了我也尝试过但没有运气的递归,同样的事情发生了。
My recursive code is below...我的递归代码如下...
s3_upload_multi: async (req, res) => {
const generatePath = (rootPath, fieldName) => {
let path;
// this is just a switch statement here to check which fieldName is provided then value of path will depend on it
// as for the other two variable is just checking if upload content type is correct
return { path };
};
const processUpload = async ({
fieldName,
awsOp,
fileExtension,
rootPath,
fileName,
}) => {
return new Promise(function (resolve, reject) {
req.file(fieldName).upload(awsOp, async (err, filesUploaded) => {
if (err) reject(err);
const filesUploadedF = filesUploaded[0]; // F = first file
const response = {
status: true,
errCode: 200,
msg: 'OK',
response: {
url: filesUploadedF.extra.Location,
size: filesUploadedF.size,
type: fileExtension,
filename: filesUploadedF.filename,
key: filesUploadedF.extra.Key,
field: fieldName,
}
};
resolve(response);
});
});
}
const process_recur = async (files, fieldName) => {
if (files.length <= 0) return;
const fileUpload = files[0].stream;
const rootPath = `${sails.config.aws.upload.path.root}`;
const fileCType = fileUpload.headers['content-type'];
// console.log(fileCType, 'fileCType');
const { path } = generatePath(rootPath, fieldName);
const fileName = fileUpload.filename;
const fileExtension = fileUpload.filename.split('.').pop();
const genRan = await UtilsService.genRan(8);
const fullPath = `${path}${genRan}-${fileName}`;
const awsOp = {
adapter: require('skipper-better-s3'),
key: sails.config.aws.access_key,
secret: sails.config.aws.secret_key,
saveAs: fullPath,
bucket: sails.config.aws.bucket,
s3params: {
ACL: 'public-read'
},
};
const config = {
fieldName,
awsOp,
fileExtension,
rootPath,
fileName,
}
const procceed = await processUpload(config);
files.shift();
await process_recur(files, fieldName);
};
try {
const fieldName = req._fileparser.upstreams[0].fieldName;
const files = req.file(fieldName)._files;
await process_recur(files, fieldName);
} catch (e) {
console.log(e, 'inside UploadService');
return false;
}
}
below is the code for me using for loop which is quite similiar from above though下面是我使用 for 循环的代码,虽然与上面的代码非常相似
s3_upload_multi: async (req, res) => {
const generatePath = (rootPath, fieldName) => {
let path;
// this is just a switch statement here to check which fieldName is provided then value of path will depend on it
// as for the other two variable is just checking if upload content type is correct
return { path };
};
const processUpload = async ({
fieldName,
awsOp,
fileExtension,
rootPath,
fileName,
}) => {
return new Promise(function (resolve, reject) {
req.file(fieldName).upload(awsOp, async (err, filesUploaded) => {
if (err) reject(err);
const filesUploadedF = filesUploaded[0]; // F = first file
const response = {
status: true,
errCode: 200,
msg: 'OK',
response: {
url: filesUploadedF.extra.Location,
size: filesUploadedF.size,
type: fileExtension,
filename: filesUploadedF.filename,
key: filesUploadedF.extra.Key,
field: fieldName,
}
};
resolve(response);
});
});
}
try {
const fieldName = req._fileparser.upstreams[0].fieldName;
const files = req.file(fieldName)._files;
for (const file of files) {
const fileUpload = file.stream;
const rootPath = `${sails.config.aws.upload.path.root}`;
const fileCType = fileUpload.headers['content-type'];
// console.log(fileCType, 'fileCType');
const fileName = fileUpload.filename;
const { path } = generatePath(rootPath, fieldName);
const fileExtension = fileUpload.filename.split('.').pop();
// using a variable here because if this is an image, a thumbnail will be created with the same name as the original one
const genRan = await UtilsService.genRan(8);
const fullPath = await `${path}${genRan}-${fileName}`;
const awsOp = {
adapter: require('skipper-better-s3'),
key: sails.config.aws.access_key,
secret: sails.config.aws.secret_key,
saveAs: fullPath,
bucket: sails.config.aws.bucket,
s3params: {
ACL: 'public-read'
},
};
const config = {
fieldName,
awsOp,
fileExtension,
rootPath,
fileName,
}
const procceed = await processUpload(config);
console.log(procceed, 'procceed');
}
} catch (e) {
console.log(e, 'inside UploadService');
return false;
}
}
Which part am I making mistake that's causing such behavior?我在哪个部分犯了导致这种行为的错误? I checked my path it's totally correct with correct filename too when I console.log
我检查了我的路径,当我console.log
时,它也完全正确,文件名也正确
Thanks in advance for any suggestions and help.在此先感谢您的任何建议和帮助。
Took me quite a lot of time to figure this out ages ago.很久以前我花了很多时间才弄清楚这一点。 Especially you are using skipper-better-s3
which did not conclude as much detailed documentation as skipper
, going back to look into skipper
documentation actually the saveAs
field doesn't only take string
but also a function
which you can then use that to get each file's filename and return it as needed so actually you do not even need to use neither resursive or for loop at all.特别是您使用的skipper-better-s3
没有像skipper
那样得出详细的文档,回过头来查看skipper
文档实际上saveAs
字段不仅需要string
而且还有一个function
,然后您可以使用它来获取每个文件的文件名并根据需要返回它,因此实际上您甚至根本不需要使用递归或 for 循环。
for example with some of your codes例如使用您的一些代码
const awsOp = {
adapter: require('skipper-better-s3'),
key: sails.config.aws.access_key,
secret: sails.config.aws.secret_key,
saveAs: (__newFileStream, next) => {
// generatePath is what you wrote
// __newFileStream.filename would the filename of each each before uploading
// the path is pretty much the s3 key which includes your filename too
const { path } = generatePath(rootPath, __newFileStream.filename, fieldName);
return next(undefined, path);
},
bucket: sails.config.aws.bucket,
s3params: {
ACL: 'public-read'
},
};
skipper
documentation https://www.npmjs.com/package/skipper#customizing-at-rest-filenames-for-uploads skipper
文档https://www.npmjs.com/package/skipper#customizing-at-rest-filenames-for-uploads
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.