Bowen Yang
Bowen Yang

Reputation: 13

Uploaded Img into Multer GridFS and End Up corrupted

I am currently trying to implement a mini Web app with MERN Pipeline.

For the app, I would like to upload/download images with MongoDB. I used GridFsStorage from Multer to upload data:

const storage = new GridFsStorage({
    url: env.MONGO_CONNECTION_STRING,
    file: (req, file) => {
      return new Promise((resolve, reject) => {
          const fileInfo = {
            bucketName: 'uploads'
          };
          resolve(fileInfo);
      });
    }
  });

router.post("/file", upload.single('fileContent'), FFController.createFile);

With createFile function:

export const createFile: RequestHandler<unknown, unknown, CreateFileBody, unknown>  = async(req, res, next) => {
    //TODO:  Authentication
    const parentId = req.body.parentId;
    try{
        if(!mongoose.isValidObjectId(parentId)){
            throw createHttpError(400, "Invalid parent Id");
        }
        const parentFolder = await FFModel.FolderModel.findById(parentId);
        if(!parentFolder || parentFolder.objectType == "FILE"){
            throw createHttpError(400, "Incorrecrt parent ID");
        }
        if(!req.file){
            throw createHttpError(400, "Please provide a file and filetype");
        }
        const title = req.file.originalname;
        const foldersAndFiles = await FFModel.FileModel.create({
            userId: undefined ,
            title: title,
            parentId: parentId,
            fileMeta: req.file.filename,
            objectType: "FILE",
        });
        res.status(201).json(foldersAndFiles);
    }catch(error){
        next(error);
    }
};

FFModel.FileModel:

const fileSchema = new Schema({
    userId: { type: Schema.Types.ObjectId, default: new mongoose.Types.ObjectId(env.DEFAULTPAGE_PARENTID)},
    title: { type: String, defualt: "none"},
    parentId: {type: Schema.Types.ObjectId, default: new mongoose.Types.ObjectId(env.DEFAULTPAGE_PARENTID)},
    objectType: {type: String},
    fileMeta:{type: String},
}, baseOptions);

The data can be upload successively through Postman and will end up storing in a Buffer in uploads.chunk in MongoDB like the following: MongoDB Chunk Data

However, in order to display the data in frontend, I tried to transfer the buffer data to base64 and test the content with https://codebeautify.org/base64-to-image-converter and it turns out the data is corrupted and can not display. Can somebody provides me some hint why this is happening?

I manage to retrieve data in backend with:

    const fileContents = await FFModel.chunkModel.find({files_id: fileMeta[0]._id});//.sort("-postDate")
    // not supporting consecutive blocks yet
    const resultFileData = {
        _id: id,
        parentId: file.parentId,
        objectType: file.objectType,
         title:file.title,
        fileContent: fileContents[0].data,
        };

Where Chunk Model is:

const chunkSchema = new Schema({
    files_id:{type: Schema.Types.ObjectId},
    data: Buffer,
}, {collection:'uploads.chunks'});
const chunkModel = model('uploads_chunks', chunkSchema);

and transport the data to frontend through:

export async function fecthFileWithId(id: string): Promise<FFModel> {
    const response = await fetchDataWrapper("http://localhost:5000/api/FF/File/" + id , { method: "GET" }); // fetchDataWrapper just a function which calls fetch()
    return response.json();
}

FFModel is:

export interface BufferData {
    data: Buffer,
    type: String,
}

export interface FF {
    _id: string,
    title: string,
    fileContent?: BufferData,
    createdAt?: string,
    updatedAt?: string,
    parentId: string,
    objectType?: string,
    __type: string
}

Thanks for your kind help!

I tried to extract data but not work

Upvotes: 1

Views: 48

Answers (1)

Bowen Yang
Bowen Yang

Reputation: 13

The problem is that I have not converted the retrieved data into an actual Buffer. The data I retrieved are an array of integers which should be converted into Buffer by

Buffer.from(file.fileContent.buffer.data).toString('base64')

Where Buffer comes from:

import { Buffer } from 'buffer';

Upvotes: 0

Related Questions