here is a part of my code of multer using nodejs
const storageEngine = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './Images')
const Files = [file.originalname]
console.log(Files)
},
filename: (req, file, cb) => {
cb(null, file.originalname)
}
})
the console log of the above code is this:
['image.png']
['image2.png']
['image3.png]
so i want all file names to be in one array to be posted in mysql in one go as i do not want to send multiple request to mysql as there are numerous amount of images.
so all i want is the file names to be present in one single array like this:
['image.png', 'image2.png', 'image3.png']
The destination event that you use is invoked once per uploaded file, so you cannot use it to collect all file names.
Assuming you have an input field <input type="file" multiple name="upload">, you can instead use
app.use(storageEngine.array("upload"))
.use(function(req, res, next) {
console.log(req.files.map(file => file.originalname));
next();
});
Related
Attaching Documents Pic
As shown in the pic i am attaching my documents.
onDrop: (acceptedFiles, rejectedFiles) => {
if (rejectedFiles.length) {
toast.error('You can upload images , Words and Excel files !.')
} else {
console.log(acceptedFiles)
setFiles([...files, ...acceptedFiles.map(file => Object.assign(file))])
}
}
axios.post('http://localhost:5000/AddEmployee', {
user, employeeDocuments : user[2].documents
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
I am storing all test documents in the employeedocuments array and then i am sending post request to backend.
employeeDocuments array in console log view
Here i am console log the employeeDocuments array it is looking fine.
enter code here
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./public/uploads");
},
filename: function (req, file, cb) {
cb(null, file.fieldname + "-" + Date.now() + path.extname(file.originalname));
},
});
var upload = multer({ storage: storage });
var uploadMultiple = upload.fields([{ name: 'employeeDocuments', maxCount: 10 }])
This is my backend multer code to upload files i have used the name employeeDocuments to upload files but multer is not uploading these files.Rather i used postman and it was working fine. But when i upload these files using react by post request these files not get uploaded.
I faced a similar issue and I was able to fix it by modifying my axios post request to sending Form Data:
const formData = new FormData()
formData.append('imagePath', image)
The have the upload in the post like this: router.post("/AddEmployee",upload, async (req, res)
And store it in the DB as a path using req.file.path
Sorry if its a bit confusing but this is everything I have in my code and its fully working
I upload an image from a react native expo app.
In the back end, I have this code :
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, "avatars");
},
filename: (req, file, callback) => {
let imagePath = Date.now() + path.extname(file.originalname);
callback(null, imagePath);
},
});
const upload = multer({ storage: storage });
app.use("/uploadAvatar", upload.single("avatar"), (req, res) => {
res.status(200).json("Image enregistrée !");
});
It works fine and save the image into a folder.
What I need to do, is to save the image path in the database.
The image is an avatar for a user profile, so I need to add its path to the user table.
Suppose you are storing the image in your middleware:
app.use('/uploadAvatar', upload.single('avatar'), async (req, res) => {
// Assume that you're storing the image with a function,
// in this case you just need to pass the filename into
// your function. This is a pseudocode and is not expected to work
// as it is, so please adjust accordingly.
const result = await storeImage(req.file.filename);
// Return the response as JSON.
res.status(200).json('Image enregistrée!');
});
Basically, you have to inspect the req.file that would be populated after you call the upload.single('avatar') middleware. In this case, we're taking the filename to be stored into the database. You can do any path/file/property manipulations that you might want to do before storing that image, though.
For further information about req.file and what properties it contains, please see the Multer documentation.
I have a local file called "space.jpg" in my server.
and now I want to upload this file with a new name to GCP bucket.
I can upload this file successfully with the below code:
const myBucket= gc.bucket('my-bucket')
app.post('/create_file', async (req, res, next) => {
myBucket.upload("space.jpg")
}
my file structure in server
server.js
space.jpg
Now I want to upload this file with a random id when users request.
e.g.
app.post('/create_file', async (req, res, next) => {
// spaceId = random string
// upload space.jpg to myBucket with the name spaceId
}
How to upload with a new name?
You will want to pass a second argument to upload(), which is an UploadOptions object. It has a property called destination where you can name the path where the file should be uploaded.
const options = {
destination: bucket.file('/path/to/newFile.jpg'),
};
myBucket.upload("space.jpg", options);
You will, of course, have to provide your own file name.
I have a form which have multiple fields one of them is file field for uploading image.
name = 'john doe'
location = 'Some location'
image = (binary)
My question is how do I validate this image file for both the times i.e CREATE AND UPDATE.
For create, every field is mandatory but for edit, user might not want to update image but only text fields hence he won't select an image file
router.post('/user', upload.single('image'), userRoute);
I have made a middleware like this but this does not give proper validation result. Let's assume that user has selected an image and pressed the submit button then I will get the like this in req.file.
{ fieldname: 'image',
originalname: 'images (2).jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'uploads/top-level',
filename: 'images (2)-1583345397445.jpg',
path: 'uploads\\top-level\\images (2)-1583345397445.jpg',
size: 33766 }
which make sense but suppose user selected some zip file which is not a file type which I want user to submit hence I have to catch it and show it to user that the file type is not an image. Let me know if i can do using above mentioned middleware.
router.post('/user', userRoute);
and i userRoute function I wrote something like this to catch the error
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
// catch error and show to user
} else if (err) {
// catch error and show to user here also
}
// Logic goes here
// and we get the req.body here
})
this is good enough for create where every field is mandatory
But for edit how can I save data to database if user is not updating image which means I am getting only two fields
name
location
If user is selecting image then I will save otherwise i will skip image and save only two fields. HOW can i achieve this and if user is not selecting correct image type then i will have to show error to user.
here is the multer code
var upload = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/top-level')
},
filename: function (req, file, cb) {
cb(null, file.originalname.split('.')[0] + '-' + Date.now() + path.extname(file.originalname))
}
}),
fileFilter: (req, file, cb) => {
if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
cb(null, true);
} else {
return cb(null, false);
}
}
});
First of all : You should have validation on both front & back ends in
order to provide the best experience possible and avoid "stupid"
errors which can (and will) ultimately become flaws just waiting to be
exploited by anyone that gets it.
Second : YOU NEVER SHOW ERRORS TO CLIENTS (EVER)..consider using the
connect-flash middleware to send a flash message either in
notifications or anywhere in your app(check docs for flash()).
On the front-end , you should block uploads of filetypes by extensions which is pretty easy either on native html or through JS ( you didn't specify your frontend so I will skip this part for the sake of clarity ).
On the backend , you can check on the "req.file.mimetype" to see if it's in an array of extensions allowed by your upload functionality.
something like this:
var authorizedMimeTypes=['jpg','jpeg',...];
if(req.file.mimetype in authorizedMimeTypes){
//your code goes here..
}else{
//your error code goes here..
};
I am making a multer storage engine which makes stream connection between client and S3 Server.
At middle of the stream, my code examine chunks and send it to S3.
I could get a file stream from node.js server. But when I request file array upload, node inspector shows only one stream. What should I do?
Stream engine snippet
CustomStreamEngine.prototype._handleFile = function _handleFile (req, file, cb) {
// for inspect
req.files.length // 1
file;
};
request controller
var streamStorage = multer({
storage: streamEngine()
});
dev.post('/rec_test', streamStorage.array('source'), (req, res, next) => {
});
I just published this streaming multipart/form-data parser on npm as form-parser:
You should be able to do the following:
dev.post('/rec_test', async (req, res, next) => {
// Parse request
await parser(req, async ({ fieldType, fieldName, fieldContent }) => {
// Log all fields
console.log({ fieldType, fieldName, fieldContent });
// Handle 'source' file fields
if (fieldType === 'file' && fieldName === 'source[]') {
// Get file info
const { fileName, fileType, fileStream } = fieldContent;
// Upload fileStream to S3 :-)
}
});
});
Hope it's helpful.
K
I think you can add some logs to https://github.com/expressjs/multer/blob/master/lib/make-middleware.js to check.
Currently, I use axios on the client to send multi files to the server with multer. And I can see all files in the function
busboy.on('file', function (fieldname, fileStream, filename, encoding, mimetype), but there is only one file at a time, and this function will call the _handfile function of the custom storage, so that I think it is the reason for your issue.
Hope it can help you