在nodejs应用程序中,我有一个可以发布图像文件的路由。然后将图像文件上载到临时文件夹,并使用bull将新作业添加到redis队列。队列的使用者将图像调整为标准web大小的图像(缩略图),提取元数据并将路径和一些信息添加到我的mongodb中。
我的问题是如何通知前端应用程序的用户文件已经上传、调整大小等,然后添加到数据库中?一旦上传,我的api就会返回一些关于添加到bull队列中的每个作业的信息。最好的方法是每隔一秒左右查询一次api来检查队列项的状态吗?
在我的本地机器上,每项作业大约需要10秒,这就是我使用队列来避免请求超时的原因。
一些代码。。。
@ApiConsumes('multipart/form-data')
@Post(':id/upload')
@UseInterceptors(
FilesInterceptor('files', 100, {
limits: {
fileSize: PhotosController.maxFileSize // A 40MB limit per file
},
storage: multer.diskStorage({
destination: PhotosController.fileDestination,
filename: (req, file, callback) => {
const name = PhotosController.createFileName(file);
callback(null, name);
}
}),
fileFilter: (req, file, callback) => {
const allowedFileTypes = ['.png', '.jpg', '.jpeg'];
const allowedMimetypes = ['image/jpeg', 'image/png'];
const fileExtension = path.extname(file.originalname).toLowerCase();
if (!allowedFileTypes.includes(fileExtension)) {
callback(new Error(`Incorrect file type: ${fileExtension}`), false);
}
if (!allowedMimetypes.includes(file.mimetype)) {
callback(
new Error(`Incorrect file mimetype: ${file.mimetype}`),
false
);
}
callback(null, true);
}
})
)
public uploadFile(
@UploadedFiles() files: any[],
@Param('id') _id: string | ObjectId
) {
if (!files) {
throw new BadRequestException('No files uploaded.');
}
files.map(file => {
file['albumID'] = _id;
return file;
});
return this.filesService.addToFileUploadQueue(files);
}
文件服务:
@Injectable()
export class FilesService {
constructor(@InjectQueue('Main') private readonly queue: Queue) {}
public addToFileUploadQueue(files): Promise<Bull.Job[]> {
const jobs = [];
for (const file of files) {
jobs.push(this.queue.add('resize', file));
}
return Promise.all(jobs);
}
}
最后,工作消费者:
@Process('resize')
public async handleTranscode(job: Job) {
try {
const file = job.data;
const ext = file.originalname.split('.')[1];
const thumbName = [
`${file.filename.split('.')[0]}_thumb`,
file.filename.split('.')[1]
].join('.');
const fileNameSansExt = file.filename.split('.')[0];
return await forkJoin([
// Create standard image
this.image.resizeToFile(
file.path,
`${this.dest}\\${file.albumID}\\`,
file.filename,
1920,
1920,
{ withoutEnlargement: true, fit: 'inside' }
),
// Create thumbnail image
this.image.resizeToFile(
file.path,
`${this.dest}\\${file.albumID}\\`,
thumbName,
50,
50,
{
withoutEnlargement: true,
fit: 'inside'
}
),
// Extract the metadata from the image
this.image.getMeta(file.path)
])
.pipe(
switchMap(([largeImage, thumb, meta]) => {
// Delete the temporary file
return this.ft
.delete(file.path)
.pipe(map(() => [largeImage, thumb, meta]));
}),
switchMap(([largeImage, thumb, meta]) => {
// Create the standard photo document and insert it into the database.
const photoDocument = {
_id: new ObjectId(),
mimetype: file.mimetype,
path: `\\${file.albumID}\\${fileNameSansExt}.${ext}`,
thumb: `\\${file.albumID}\\${fileNameSansExt}_thumb.${ext}`,
imageDimensions: {
width: largeImage.width,
height: largeImage.height
},
thumbDimensions: {
width: thumb.width,
height: thumb.height
},
encoding: file.encoding,
size: largeImage.size,
thumbSize: thumb.size,
meta: meta
};
return this.photosService
.updateAlbum(
file.albumID,
{ $push: { photos: photoDocument } },
{ upsert: true }
)
.pipe(map(dbResult => ({ largeImage, thumb, meta, dbResult })));
})
)
.pipe(
tap(result => {
if (process.env.NODE_ENV === 'development') {
console.log(result);
}
})
)
.toPromise();
} catch ($e) {
console.log($e);
}
}
如果这个问题涉及面太广,我很抱歉。我只是想听听你的想法。
注意:这是对api使用nestjs,对ui使用react,对队列使用bull和redis。
暂无答案!
目前还没有任何答案,快来回答吧!