Meteor-Files
Meteor-Files copied to clipboard
Is it acceptable to convert a base64 string to a Buffer on the server for the `write` function?
Hi, so in my Meteor/Apollo/React stack my current approach has been to upload images to the server by sending the base64 string to the server, and then storing it.
I have a canvas and hence I need to run a .toDataURL() function on it to get it as a base64 string. I'd rather not upload it from the client side that's why I'm not using the insert function (my main concern with this is, is there any danger to this? How do I protect against malicious uploads on the client side? There isn't any permission setting or anything of that sort in the function so I'm not sure if this exposes things too much).
As I'm not entirely sure how that can be done, I've sent the base64 string over and convert it into a Buffer on the server. I drop the beginning of the base64 string which is data:image/png;base64,, so I just extract everything after the first comma.
const data = image.substring(image.indexOf(',') + 1)
Images.write(Buffer.from(data, 'base64'), {
fileName: `${user._id}_${Date.now()}.png`,
type: 'image/png'
}, (writeError, fileRef) => {
if (writeError) {
throw writeError
} else {
console.log(`${fileRef.name} is successfully saved to FS. _id: ${fileRef._id}`)
}
})
Is this acceptable practice? I was curious because if it is acceptable, I was wondering why write does not accept a base64 string as an input format. Just want to make sure this isn't a hacky approach that's bypassing something important.
As a separate question, is it possible to make this call synchronous? This function lies inside a query function and I would like to return the resulting fileRef._id, but I can't do so as this function is asynchronous. Is there any way for me to "force" this to be synchronous? If not, it's fine too!
Thanks!
my main concern with this is, is there any danger to this? How do I protect against malicious uploads on the client side? There isn't any permission setting or anything of that sort in the function so I'm not sure if this exposes things too much
I've just started using Meteor and I kind of had the same questions. In core Meteor you should never use insert but use methods. That's why I was confused that this package uses insert etc. directly on the collection and claims "no need to learn new APIs".
Anyway, you can do the same checks you do in a method inside onBeforeUpload. You have access to this.userId, exactly like in a method. So much for "no need to learn new APIs".
I think the docs could make that more clear.
Regarding your other question: I don't think this is acceptable practice. A large Base64 string will lock up both the client and server (e.g. toDataURL is synchronous). You also lose features such as upload progress. I think the correct solution is to use canvas.toBlob and create an File from it. Then use the regular insert API so it will be uploaded in chunks.
@ajaypillay It's totally fine to get canvas as base64. Just upload it via .insert as base64 string
As a separate question, is it possible to make this call synchronous? This function lies inside a query function and I would like to return the resulting fileRef._id, but I can't do so as this function is asynchronous. Is there any way for me to "force" this to be synchronous? If not, it's fine too!
Our API is event-driven, just wait for 'end' on Client and onAfterUpload on Server events and use newly inserted _id as needed
@Prinzhorn
I've just started using Meteor and I kind of had the same questions. In core Meteor you should never use insert but use methods. That's why I was confused that this package uses insert etc. directly on the collection and claims "no need to learn new APIs".
This package mimics Mongo Collection API, .insert() method just have the same name and accept arguments in the similar way.
Meteor-Files would take care of large file or base64 string and send it to the server in small chunks
Hope that helps, let me know
P.S. I'm sorry for the late reply
Closed due to silence at issue owner end. Feel free to reopen it in case if the issue still persists on your end.