diff --git a/backend/db/mongoDB/fileDB.ts b/backend/db/mongoDB/fileDB.ts index b488b70..97029cb 100644 --- a/backend/db/mongoDB/fileDB.ts +++ b/backend/db/mongoDB/fileDB.ts @@ -141,6 +141,20 @@ class DbUtil { return file; }; + setThumbnail = async (fileID: string, thumbnailID: string) => { + const file = await File.findOneAndUpdate( + { _id: new ObjectId(fileID), "metadata.hasThumbnail": false }, + { + $set: { + "metadata.hasThumbnail": true, + "metadata.thumbnailID": thumbnailID, + }, + } + ); + + return file; + }; + removeOneTimePublicLink = async ( fileID: string | mongoose.Types.ObjectId ) => { diff --git a/backend/services/chunk-service/utils/createImageThumbnail.ts b/backend/services/chunk-service/utils/createImageThumbnail.ts index 3c0885d..d93adf3 100644 --- a/backend/services/chunk-service/utils/createImageThumbnail.ts +++ b/backend/services/chunk-service/utils/createImageThumbnail.ts @@ -1,29 +1,115 @@ -import mongoose from "../../../db/connections/mongoose"; import crypto from "crypto"; import Thumbnail from "../../../models/thumbnail-model"; import sharp from "sharp"; import { FileInterface } from "../../../models/file-model"; import { UserInterface } from "../../../models/user-model"; -import fs, { write } from "fs"; import uuid from "uuid"; import env from "../../../enviroment/env"; -import { ObjectId } from "mongodb"; -import File from "../../../models/file-model"; import { createGenericParams } from "./storageHelper"; import { S3Actions } from "../actions/S3-actions"; import { FilesystemActions } from "../actions/file-system-actions"; +import { EventEmitter } from "stream"; +import FileDB from "../../../db/mongoDB/fileDB"; -const conn = mongoose.connection; +const fileDB = new FileDB(); const storageActions = env.dbType === "s3" ? new S3Actions() : new FilesystemActions(); -const waitTimer = () => { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve(null); - }, 5000); - }); +const processData = ( + file: FileInterface, + filename: string, + user: UserInterface +) => { + const eventEmitter = new EventEmitter(); + + try { + const password = user.getEncryptionKey(); + + let CIPHER_KEY = crypto.createHash("sha256").update(password!).digest(); + + const thumbnailFilename = uuid.v4(); + + const thumbnailIV = crypto.randomBytes(16); + + const params = createGenericParams({ + filePath: file.metadata.filePath, + Key: file.metadata.s3ID, + }); + + const readStream = storageActions.createReadStream(params); + + const { writeStream, emitter } = storageActions.createWriteStream( + params, + readStream, + thumbnailFilename + ); + + const decipher = crypto.createDecipheriv( + "aes256", + CIPHER_KEY, + file.metadata.IV + ); + + const imageResize = sharp().resize(300); + + const handleFinish = async () => { + const thumbnailModel = new Thumbnail({ + name: filename, + owner: user._id, + IV: thumbnailIV, + path: env.fsDirectory + thumbnailFilename, + s3ID: thumbnailFilename, + }); + + await thumbnailModel.save(); + + const updatedFile = await fileDB.setThumbnail( + file._id!.toString(), + thumbnailModel._id.toString() + ); + + if (!updatedFile) { + throw new Error("Thumbnail Not Set"); + } + + eventEmitter.emit("finish", updatedFile); + }; + + const handleError = (e: Error) => { + eventEmitter.emit("error", e); + }; + + readStream.on("error", handleError); + + writeStream.on("error", handleError); + + decipher.on("error", handleError); + + imageResize.on("error", handleError); + + const thumbnailCipher = crypto.createCipheriv( + "aes256", + CIPHER_KEY, + thumbnailIV + ); + + readStream + .pipe(decipher) + .pipe(imageResize) + .pipe(thumbnailCipher) + .pipe(writeStream); + + if (emitter) { + emitter.on("finish", handleFinish); + } else { + writeStream.on("finish", handleFinish); + } + } catch (e) { + eventEmitter.emit("error", e); + } + + return eventEmitter; }; const createThumbnail = ( @@ -31,122 +117,15 @@ const createThumbnail = ( filename: string, user: UserInterface ) => { - return new Promise(async (resolve, reject) => { - try { - const password = user.getEncryptionKey(); - - let CIPHER_KEY = crypto.createHash("sha256").update(password!).digest(); - - const thumbnailFilename = uuid.v4(); - - const thumbnailIV = crypto.randomBytes(16); - - console.log("file metadata", file.metadata); - - // if (env.dbType === "s3") { - // await waitTimer(); - // } - - const params = createGenericParams({ - filePath: file.metadata.filePath, - Key: file.metadata.s3ID, - }); - - const readStream = storageActions.createReadStream(params); - - const { writeStream, emitter } = storageActions.createWriteStream( - params, - readStream, - thumbnailFilename - ); - - const decipher = crypto.createDecipheriv( - "aes256", - CIPHER_KEY, - file.metadata.IV - ); - - const imageResize = sharp().resize(300); - - const handleFinish = async () => { - try { - const thumbnailModel = new Thumbnail({ - name: filename, - owner: user._id, - IV: thumbnailIV, - path: env.fsDirectory + thumbnailFilename, - s3ID: thumbnailFilename, - }); - - await thumbnailModel.save(); - if (!file._id) { - return reject(); - } - const updateFileResponse = await File.updateOne( - { _id: new ObjectId(file._id), "metadata.owner": user._id }, - { - $set: { - "metadata.hasThumbnail": true, - "metadata.thumbnailID": thumbnailModel._id, - }, - } - ); - if (updateFileResponse.modifiedCount === 0) { - return reject(); - } - - const updatedFile = await File.findById({ - _id: new ObjectId(file._id), - "metadata.owner": user._id, - }); - - if (!updatedFile) return reject(); - - resolve(updatedFile?.toObject()); - } catch (e) { - console.log("thumbnail error", e); - resolve(file); - } - }; - - const handleError = (e: Error) => { - console.log("thumbnail stream error", e); - resolve(file); - }; - - readStream.on("error", handleError); - - writeStream.on("error", handleError); - - decipher.on("error", handleError); - - imageResize.on("error", handleError); - - const thumbnailCipher = crypto.createCipheriv( - "aes256", - CIPHER_KEY, - thumbnailIV - ); - - readStream - .pipe(decipher) - .pipe(imageResize) - .pipe(thumbnailCipher) - .pipe(writeStream); - - if (emitter) { - emitter.on("finish", async () => { - await handleFinish(); - }); - } else { - writeStream.on("finish", async () => { - await handleFinish(); - }); - } - } catch (e) { - console.log("File service upload thumbnail error", e); + return new Promise((resolve, _) => { + const eventEmitter = processData(file, filename, user); + eventEmitter.on("error", (e) => { + console.log("Error creating thumbnail", e); resolve(file); - } + }); + eventEmitter.on("finish", (updatedFile: FileInterface) => { + resolve(updatedFile); + }); }); }; diff --git a/backend/services/chunk-service/utils/getFolderUploadBusboyData.ts b/backend/services/chunk-service/utils/getFolderUploadBusboyData.ts index 87e3350..c381292 100644 --- a/backend/services/chunk-service/utils/getFolderUploadBusboyData.ts +++ b/backend/services/chunk-service/utils/getFolderUploadBusboyData.ts @@ -140,12 +140,10 @@ const processData = (busboy: any, user: UserInterface) => { ); writeStream.on("error", (e: Error) => { - console.log("write stream error", e); reject(e); }); cipher.on("error", (e: Error) => { - console.log("cipher error", e); reject(e); }); @@ -177,7 +175,7 @@ const processData = (busboy: any, user: UserInterface) => { fileDataMap[currentFile!.index] = { ...fileDataMap[currentFile!.index], - uploadedFileId: file._id.toString(), + uploadedFileId: file._id!.toString(), }; filesProcessed++; @@ -187,7 +185,6 @@ const processData = (busboy: any, user: UserInterface) => { } } } catch (e) { - console.log("error", e); eventEmitter.emit("error", e); } @@ -228,11 +225,9 @@ const processData = (busboy: any, user: UserInterface) => { ); busboy.on("error", (e: Error) => { - console.log("busboy error", e); eventEmitter.emit("error", e); }); } catch (e) { - console.log("get folder busboy data error", e); eventEmitter.emit("error", e); } diff --git a/src/components/UploadItem/UploadItem.tsx b/src/components/UploadItem/UploadItem.tsx index 3e57792..100ba2e 100644 --- a/src/components/UploadItem/UploadItem.tsx +++ b/src/components/UploadItem/UploadItem.tsx @@ -32,12 +32,12 @@ const UploadItem: React.FC = (props) => { const ProgressBar = memo(() => { if (completed) { return
; + } else if (canceled) { + return
; } else if (type === "file") { return ( ); - } else if (canceled) { - return
; } else { return ; }