I post formdata which includs image file to node server.
This is server request code.
const multer = require('multer')
const avatar = multer({dest: 'public/avatar/'})
app.post('/uploadPhoto', avatar.single('file'), function(req, res) {
console.log(req.file)
})
This is console result.
file: {
fieldname: 'file',
originalname: 'git - Copy.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'public/avatar/',
filename: 'ac578f8b2b1a629c89f85d3a7215ed18',
path: 'public\\avatar\\ac578f8b2b1a629c89f85d3a7215ed18',
size: 4786565
}
And I can see public/avatar/ac578f8b2b1a629c89f85d3a7215ed18 on my computer.
But I can't open it.
How to convert request file data to correct image type data.
Now if I try to open it, I can get this sentence.
The file is not displayed in the editor because it is either binary or uses an unsupported text encoding.
We need to specify the extension of the file we are trying to save. You can use the diskstorage engine to have more control over how files are stored in the disk.
const storage = multer.diskStorage({
destination: function(req,file,callback){
const path = `/public/avatar/`;
callback(null, path);
},
filename: function(req,file,callback){
callback(null,`${file.originalname}`);
}});
In the file object, we have all the properties of file like originalname and we can use this to set filename.
Finally, pass this in multer
const upload = multer({storage: storage});
Related
I'm trying to get Multer to save images in an src/uploads directory. Everything seems to work fine with no errors but the src/uploads directory is empty after the endpoint is called.
I'm using a microservices architecture using Node, Express, and running it locally DockerDesktop + Kubernetes using Skaffold.
Here is my route:
const router = express.Router();
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, './uploads'));
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
});
let upload = multer({ storage });
router.post(
'/api/products/images',
upload.single('image'),
async (req: Request, res: Response) => {
console.log(req.file);
res.status(201).send('success');
},
);
export { router as imageRouterRouter };
My app file includes:
app.use(imageRouterRouter);
app.use('/uploads', express.static(__dirname));
I know I'm receiving the file successfully via postman, Multer is 'uploading' it and the path is correct as I'm logging the following req.file:
[products] {
[products] fieldname: 'image',
[products] originalname: 'cute-dog.jpeg',
[products] encoding: '7bit',
[products] mimetype: 'image/jpeg',
[products] destination: '/app/src/uploads',
[products] filename: 'cute-dog.jpeg',
[products] path: '/app/src/uploads/cute-dog.jpeg',
[products] size: 18473
[products] }
Any help would be much appreciated as I've spent a couple days on it with no luck. Thanks.
I figured out what the problem was.
I was checking the src/uploads directory on my LOCAL machine, expecting it to contain the new files. But because I'm using docker, the new files were written to the container instead.
Using the below, I explored the container and confirmed the files were there:
docker exec -it <container_id> /bin/sh
Hope this helps anyone else who is as silly as me.
I'm using Multer/multer-storage-cloudinary to upload images directly to Cloudinary rather first uploading it to a local temp directory, then sending it to Cloudinary:
const express = require('express');
const router = express.Router({mergeParams:true});
if (app.get('env') == 'development'){ require('dotenv').config(); }
const crypto = require('crypto');
const cloudinary = require('cloudinary').v2;
const { CloudinaryStorage } = require('multer-storage-cloudinary');
const multer = require('multer');
const { storage } = require('../cloudinary');
const upload = multer({storage});
//configure cloudinary upload settings
cloudinary.config({
cloud_name:process.env.CLOUDINARY_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
});
const storage = new CloudinaryStorage({
cloudinary: cloudinary,
folder: ('book_tracker/'+process.env.CLOUDINARY_FOLDER+'posts'),
allowedFormats: ['jpeg', 'jpg', 'png'],
filename: function (req, file, cb) {
let buf = crypto.randomBytes(16);
buf = buf.toString('hex');
let uniqFileName = file.originalname.replace(/\.jpeg|\.jpg|\.png/ig, '');
uniqFileName += buf;
console.log(req.body);
cb(undefined, uniqFileName );
}
});
const middleware = {
function asyncErrorHandler: (fn) =>
(req, res, next) => {
Promise.resolve(fn(req, res, next))
.catch(next);
}
}
/* POST create user page */
router.post('/register', upload.single('image'), asyncErrorHandler(postRegister));
What I'm running into is that the response I'm getting in req.file is not the full Cloudinary response which includes public_id, etc. Instead it's like this:
{
fieldname: 'image',
originalname: 'My Headshot.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
path: 'https://res.cloudinary.com/<cloudinary_name>/image/upload/v1611267647/<public_id>.jpg',
size: 379632,
filename: '<public_id>'
}
It's been a while since I worked with multer-storage-cloudinary, though that storage was taken directly from an old project that would return the correct information. Is there something in multer, or multer-storage-cloudinary, that I need to set in order to put the full cloudinary response into req.file?
The multer-storage-cloudinary package is a third party package that integrates multer and Cloudinary in a streamlined way, but it doesn't expose all possible options or responses from the Cloudinary SDK or API
In your example, it's not returning the full API response from Cloudinary, but a subset of the fields, because the file object's filename, path, and size properties are taken from the Cloudinary API response (from the public_id, secure_url, and bytes properties of the API response respectively), but the other fields aren't mapped: https://github.com/affanshahid/multer-storage-cloudinary#file-properties
If you need the full set of response values (or some specific values not mapped already) you can:
Ask the package maintainer to add support for other fields
Fork the package and map additional fields yourself; the fields are mapped here though I'm not sure what else may need to be changed: https://github.com/affanshahid/multer-storage-cloudinary/blob/1eb903d44ac6dd42eb1ab655b1e108acd97ed4ca/src/index.ts#L83-L86
Switch from using that package for wrapping the Cloudinary SDK to use the Cloudinary SDK directly in your own code, so you can handle the response directly.
Leave it as it is now and make a separate call to the Cloudinary Admin API to fetch the other details of the image(s): https://cloudinary.com/documentation/admin_api#get_resources
Leave it as-is, but add a notification_url so that as well as the API call response, the details of the new upload will be sent in an HTTP POST request to a URL of your choice: https://cloudinary.com/documentation/notifications
The notification_url can be specified in the Upload API call, Upload Preset, or at the account-level in the Cloudinary account settings.
So part of my Schema looks like this photo: [{data: Buffer, contentType: String }]
And Multer stores the images like so:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads');
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now());
}
});
app.use(multer({
storage: storage
}).single('photo'));
Now I know it stores the images as a Buffer in Mongodb and stores the files on the server too. I would like it stored the path to the file in the database and then have it store the actual image file on the server. It stores the images as text files it seems, encoded with utf-8. This is an awfully complicated process for a seemingly simple task (store images)
You can access the path of the file using the req.file.path
app.post("/file", function(req, res) {
console.log(req.file.path)
})
I'm fairly new to nodejs/ express, but no matter what I seem to do I cant seem to get multer to save to the specified destination, it seems to completely ignore the parameter all together. The code is shown below
//app.js
var multer = require('multer');
var fs = require('fs');
var apiRouter = express.Router();
var app = express();
var store = multer.diskStorage({
filename: function(req,file,cb){
console.log("filename");
cb(null, Date.now()+'.'+file.originalname);
},
desitnation: function(req,file,cb){
console.log("storage");
cb(null,'./public/');
}
});
var upload = multer({storage:store}).single('file');
apiRouter.post('/upload', function(req, res){
upload(req, res, function (err) {
if (err) {
return res.end(err.toString());
}
console.log(req.file);
return res.json({originalname:req.file.originalname, uploadname:req.file.filename});
});
});
The response I get when uploading is shown below:
GET /vendor.js.map 200 3.916 ms - 6636755
filename
{ fieldname: 'file',
originalname: 'Desert.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'C:\\Users\\Dwyer\\AppData\\Local\\Temp',
filename: '1538979138829.Desert.jpg',
path:
'C:\\Users\\Dwyer\\AppData\\Local\\Temp\\1538979138829.Desert.jpg',
size: 845941 }
POST /api/upload 200 70.031 ms - 69
It seems to be setting the file correctly, but I'm not sure where it gets the destination from, no3 do I understand why the destination parameter isn't being read.
Its actually "destination" (not desitnation). You should also make sure that you have a folder ,with the specified name, at the specified destination.
Do you try using physical address in destination? I guess destination in multer document is physical address in linux os.
but no matter what I seem to do I cant seem to get multer to save to the specified destination, it seems to completely ignore the parameter all together.
This is because there seem to be a typo in the configuration.
'use strict';
var store = multer.diskStorage({
filename: function (req, file, cb) {
console.log("filename");
cb(null, Date.now() + '.' + file.originalname);
},
destination: function (req, file, cb) { // it is destination not desitnation :)
console.log("storage");
cb(null, './public/');
}
});
I'm using Multer and express to add image via a form. I have successfully created the file in an uploads folder. When I try to call the url it is being downloaded in a file format. I need to open it in a new tab based on mime type.
What is the best way to achieve this?
Below is my code:
app.use('/images', express.static(__dirname + '/file/uploads/'));
Sample url:
http://localhost:2020/images/b78339184694e2e6864a77d4f3067db5
I added filename in my storage variable to achieve the required result.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, __dirname+'/file/uploads/')
},
filename: function (req, file, cb) {
console.log(file);
var extArray = file.mimetype.split("/");
var extension = extArray[extArray.length - 1];
var name = crypto.randomBytes(10).toString('hex');
cb(null, name + Date.now()+ '.' +extension)
}
});