how to save image file to sequelize db using node.js - node.js

First, I send the image file from android to node.js
and I want to save the image file to the DB using node.js.
But I don't know how to do that.
This is my Node.js code
.post('/picture', upload.single('files'), (req,res)=>{
res.json(req.file)
console.log(req.body)
console.log(req.file)
})
This is the result from req.file:
fieldname: 'files',
originalname: 'CHOIHYOGIL.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'images/',
filename: 'c98531598c04abda7e936ef310b147e9',
path: 'images\\c98531598c04abda7e936ef310b147e9',
size: 1372912
I want to save this image to my MySQL DB.

You could save the file locally and store the file directory in the table.

Related

Node Js Error uploading to S3 : TypeError [ERR_INVALID_ARG_TYPE]

I'm trying to get an image uploaded to my amazon s3 bucket, but I keep getting the error
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string, Buffer, ArrayBuffer, Array,
or Array-like Object.
So basically I know I have to change it to a buffer, after some searching i tried a few solutions but non of them are working, can someone help point out to me what I'm going wrong?
const s3Client = s3.s3Client;
const params = s3.uploadParams;
//const fileContent = fs.readFileSync(req.file); <-- tried this and still gave the same error
var fileContent = Buffer.from(req.file, 'base64')
params.Key = req.file.filename
params.Body = fileContent
console.log(req.file)
s3Client.upload(params, (err, data) => {
if (err) {
res.status(500).json({error:"Error -> " + err});
}
res.json({message: 'File uploaded successfully! -> keyname = ' + req.file.originalname});
});
This is the image itself, maybe I'm converting it wrongly? The details are taken from the req.file console log
{
fieldname: 'image',
originalname: 'Kimmi.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: './images/',
filename: 'c6b46e20-4efc-11ea-8b6a-1b4d698f6335.jpeg',
path: 'images\\c6b46e20-4efc-11ea-8b6a-1b4d698f6335.jpeg',
size: 35920
}
I am not quite sure, but I think that you are using multer ?
If you are using multer you can basically use req.file.buffer.
My advice is to use stream instead of buffer if images are big
Stream example

nodejs multer retrieve stored images to the client side

I have created file storage in nodejs application to store images in uploads folder. which works fine but now I want to display those images I have read some other posts but I am still quite unsure.
Here is my code:
var Storage = multer.diskStorage({
destination: function(req, file, callback) {
var pathname = file.originalname;
var path = pathname[0].replace('_','/');
cb(null,'./uploads'+pathname);
},
filename: function(req, file, callback) {
var pathname = file.originalname;
var filename = pathname[1];
if(pathname!=undefined)
callback(null, pathname);
}
});
var upload = multer({ storage: Storage }).single('file');
router.post('/upload', multer({dest:'./uploads/'}).single('file'), function(req,res)
{
return res.status(201).json({result:req.file});
});
from console log I get
{ fieldname: 'file',
originalname: '1569402978357.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: './uploads/',
filename: 'ada9282345565e8a77c6adc4b2d15836',
path: 'uploads\\ada9282345565e8a77c6adc4b2d15836',
size: 170272 }
and in the uploads it is stored as filename
my problem is how can I display this image back? should call it from stored filename or should I change the storage to save it as original filename with file extension?
The choice to keep the original file name differs from use case to use case. In either case you will have to store the name somewhere in a persistence medium (like a database) so that while displaying it back you can look into your uploads directory and send the file back.
Depending on your use case, if you want to store the files in a different name, you need a way to find the files at a later stage. It can be achieved by storing the names in a database or you could even use some kind of formula to find out the file name of the stored file from the original one.
E.g:
name_of_stored_file = md5(name_of_original_file)
As files (images) are now stored in your backend, you can expose some API to send the files to client on request. Again this completely depends on the use case, but here's a simple example of using Expressjs res.sendFile method:
app.get('/file/:fileName', function (req, res) {
const filePath = // find out the filePath based on given fileName
res.sendFile(filePath);
});
http://expressjs.com/en/api.html#res.sendFile

handling file uploads in Nodejs with AWS

I have a server in Node.js and say I have a POST request that uploads a multipart file to my server and then I upload it to AWS S3.
The issue is, with multer, I have to save the file to disk first.
If I deploy my server onto EC2 then how will file uploading work as it won't have a destination to temporarily store the file?
Thanks!
You can use streams with busboy. I don't have experience with the AWS Node SDK, but here's the general idea:
req.busboy.on('file', function (fieldname, file, filename) {
const params = { Bucket: 'bucket', Key: 'key', Body: file };
s3.upload(params, (err, data) => {
console.log(err, data);
});
});

Referencing multiple files upload to DB with node.js

I can't understand how to save references (filenames) of multiple files upload to the database using Node.Js.
I'm using blueimp jquery file upload and multer middleware to perform a multiple files upload to the local storage (uploads folder).
<input id="fileupload" type="file" name="images" data-url="/record/edit/#{record.id}" multiple>
app.js code:
//using multer to upload files
const upload_images = upload.fields([{ name: 'featured_img', maxCount: 1 }, { name: 'images', maxCount: 8 }]);
//...
app.post('/record/edit/:id', upload_images, recordController.postUpdate );
recordController.js code:
exports.postUpdate = ((req, res, next) => {
Record.findById(req.params.id, (err, record) => {
if (req.files ) {
console.log('UPLOADED')
// record.featured_img = req.files['featured_img'][0].filename; //=> working for single file
// Now, how to make it work for multiple files?
console.log(req.files['images'])
record.images = "HOW TO SAVE THE INFO OF REQ.FILES TO DB?";
}
console.log output:
UPLOADED
[ { fieldname: 'images',
originalname: 'slippry-02.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'C:\\Users\\agaez\\Documents\\sanbox\\nodeApps\\theapp\\uploads',
filename: '8mdnuacm1469201049450.jpg',
path: 'C:\\Users\\agaez\\Documents\\sanbox\\nodeApps\\theapp\\uploads\\8mdnuacm1469201049450.jpg',
size: 49798 } ]
POST /record/edit/578580b43c7a08601730cc06 302 26.654 ms - 82
UPLOADED
[ { fieldname: 'images',
originalname: 'slippry-03.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'C:\\Users\\agaez\\Documents\\sanbox\\nodeApps\\theapp\\uploads',
filename: 'yrnnzl9h1469201049467.jpg',
path: 'C:\\Users\\agaez\\Documents\\sanbox\\nodeApps\\theapp\\uploads\\yrnnzl9h1469201049467.jpg',
size: 49792 } ]
Update
I'm using MongoDB as database and mongoose as ODM
More info: Curretly, I'm using jquery file upload which is making 2 post request when I upload 2 images. Without jquery file uploads it makes 1 post req for all the images uploaded and I get the req.files a unique array (with all the files uploaded). How can I save that info to MongoDB?
recordModel.js
//...
images: String,
//...
Your 'images' property looks just like a single String value, so if you are looking for just a comma separated string of URLs the easiest thing would be to just bring in Lodash and create the string like so:
record.images = _.map(req.files['images'], 'path').join(',');
That said, I think in reality you don't want just a single string, but instead you'd do well (I think) to define an ImageSchema that includes some or all of the information you're getting from req.files. At minimum, I'd pull in the path and the mimeType, but other info could be useful to you, I don't know. In any case, given that you have an ImageSchema defined, you could do:
const Image = mongoose.model('Image');
/* your upload stuff happens, and then */
record.images = _.map(req.files['images'], function(i){ return new Image(i);});
That assumes of course that you update your RecordSchema to be:
...
images : [ImageSchema]
...
Hope that helps.

File uploading in Amazon S3 with Node.js

I am using aws-sdk to upload files on Amazon S3. It is working fine and uploading files, but my problem is; it changed file name after uploaded to the server. For example, if I upload sample.jpg, and it renamed to something like b4c743c8a2332525.jpg. Here is my code.
AWS.config.update({
accessKeyId: key,
secretAccessKey: secret
});
var fileStream = fs.createReadStream(path);
fileStream.on('error', function (err) {
if (err) { throw err; }
});
fileStream.on('open', function () {
var s3 = new AWS.S3();
s3.putObject({
Bucket: bucket,
Key: directory + file,
Body: fileStream
}, function (err) {
if (err)
res.send(err);
fs.unlinkSync(path);
});
});
Is it normal to change file name after uploaded files to S3 server, or is there any options to upload the same file name? Thank you.
Neither S3 nor the AWS SDK pick arbitrary file names for things you upload. The names are set by your own code.
Check the value of directory + file when you set it as the S3 object key. You may be uploading 'sample.jpg' from your browser (so the file is called sample.jpg locally on your disk), but the temporary file name that node.js uses to identify the file on it's disk may be using a hash like b4c743c8a2332525.jpg.

Resources