Referencing multiple files upload to DB with node.js - 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.

Related

Merge PDF from a distant URL, with pdfkit

I have resources as PDF stored in AWS S3 bucket. I know their URL
I would like, given a list of desired PDF, get them, concat them in a single file, reupload all of it in S3, and return the new URL to be displayed in the browser
I would like if possible to use pdfkit librairy, in order to use a librairy already present in my application.
I have this so far :
public async concat2(filesId: string[]): Promise<boolean> {
const doc = new PDFDocument({ margin: 40, size: 'A4' });
filesId.map(id => doc.file(Buffer.from(`https://path-to-s3.com/${id}`)));
doc.end();
const promises: Promise<unknown>[] = [
this.s3
.upload({
Key: `test-concat.pdf`,
Bucket: 'my-s3-bucket',
Body: doc,
ContentType: 'application/pdf',
})
.promise(),
];
await Promise.all(promises);
return true;
}
The problem is I get a single-file blank file, as if the Buffer data from the existing files was null.
I even tried to reference a local file instead of the Buffer with :
doc.text('Hello world!');
doc.file('assets/pdf/test.pdf');
the result was a single-file document with "hello world", but no other data whatsoever.
What am I missing?

Multer super slow upload after recieving post request with images

Hello I'm on a (ReactJs Node Mysql Express) stack, my website has an events tab which the admin could upload to it events.
Each event has a cover photo, inner photos, Title, and a brief text.
So I send this whole form in a single post request (is it good?)
var fileUpload = multer({ storage:storage,
limits:{fileSize:150*1024*1024}
})
const multipleUpload = fileUpload.fields([{ name: 'coverPhoto', maxCount: 1 }, { name: 'innerPhotos', maxCount: 30 }])
const storage = multer.diskStorage({
destination: (req, files, cb) => {
cb(null, '../client/build/imgs/events')
},
filename: (req, files, cb) => {
cb(null, files.originalname)
}
})
The server does recieve the request perfectly but after multer receives the photos it takes so long to move them to the fs and the reverse proxy would send a 524 error that it took so long knowing that the format is webp and the photos are so small in size.
Any idea why is it taking so long?
I tried to move to formidable but I couldn't figure how to retrieve multiple input fields with multiple files in it ( I only succeeded in sending one input not multiple inputs)
Thank you

how to save image file to sequelize db using 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.

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

How do I upload images using MongoDB + Node.js (Express.js)?

I also use Mongoose, if that is relevant. I am trying to allow users to upload a profile picture. There must be a simple way, isn't there?
I think you should try multer.
Simple from multer site:
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
app.post('/upload', uploads.any(), function(req,res){
res.send(req.files);
});
It should upload file in your uploads folder (under root), and return file in JSON.
In this example you will see how to store the file you are sending in to your server directory and then pick them up from there and save them. You can also directly save them. First you pick up the file using angular, you can use anything, if you want you can check here for more details. Here is my small example the code is in jade.
<input type="file" name="file" onchange="angular.element(this).scope().selectFile(this.files)"/>
<button ng-click="savePhoto()">Save </button>
In your angular controller
$scope.savePhoto = function () {
var fd = new FormData();
fd.append("file", $scope.files[0]);
)) ;
$http.post("/xxx/photos", fd, {
withCredentials: true,
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (data) {
$scope.image = data; // If you want to render the image after successfully uploading in your db
});
};
Install multer using npm in your back end. And then in app.js you can set up a middleware to collect the files you are sending in. Just do console.log(req) here to check if you are getting the files till here. Multer does the magic here.
app.use(multer({
dest: path.join(__dirname, 'public/assets/img/profile'),
rename: function (fieldname, filename, req, res) {
console.log(req)// you will see your image url etc.
if(req.session.user) return req.session.user.id;
}
}));
So here the image will be stored in this path (public/assets/img/profile) in your server. Now you pick up the file from this server and add to your db.
var path = require('path');
var imgPath =path.join(__dirname, '../public/assets/img/profile/' + id + '.jpg'); // this is the path to your server where multer already has stored your image
console.log(imgPath);
var a ;
a = fs.readFileSync(imgPath);
YourSchema.findByIdAndUpdate( id, {
$set:
{'img.data' : a,
'img.contentType' : 'image/png' }
}, function(err, doc) {
if (err)console.log("oi");
}
);
//In case you want to send back the stored image from the db.
yourSchema.findById(id, function (err, doc) {
if (err)console.log(err);
var base64 = doc.img.data.toString('base64');
res.send('data:'+doc.img.contentType+';base64,' + base64);
});

Resources