Reputation: 13
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
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