Image Uploading in NodeJS - node.js

I am trying to upload image on the server in NodeJS using multer and I was successful in my task but the thing is I want to send back the file object to the client.
Here is the some piece of the code
uploadRouter.route('/')
.post(authenticate.verifyUser, authenticate.verifyAdmin, upload.single('imageFile'), (req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
console.log(req);
res.json(req.file);
})
When I send the request in postman to the server. It is showing 200 status. File is also uploaded on the server but in postman response it's showing blank.
Here is the screenshot of postman
When I logged the req.file object it's showing undefined
but when I logged req object here is what I got
IncomingMessage {
.....
file: {fieldname: 'imageFile', originalname: 'alberto.png', encoding: '7bit', mimetype: 'image/png', destination: 'public/images', …}
.....
}
if this file object is inside the req object then why I am not able to access by req.file?

Related

Send req.file to another EndPoint using multer result is undefined

I'm trying to send the filesI received using multer to another endpoint but on the other endpoint I get undefined req.file
- Here I have created a form and added the data I received to it, then I'm sending it to the other endpoint using axios
const body = new FormData();
body.append('file', Readable.from(req.files[i].buffer)),{
filename: req.files[i].originalname,
}
body.append('mimetype' , req.files[i].mimetype);
const response = await axios.post("http://localhost:8080/api/image/images/create", body, {
headers: {
"Content-Type": "multipart/form-data",
},
})
- Here I'm using multer in the other endpoint, however in the controller the file I get is undefined, I only receive the body of the request
const multer = require('multer')
const upload = multer({ dest: 'uploads/' })
imageRouter.post('/images/create', upload.single("file"), imageController.postImage);
Try not including headers, and also try appending file buffer without converting it to stream. Also, mimetype can be included in the file information object.
Try this:
const body = new FormData();
body.append('file', req.files[i].buffer, {
filename: req.files[i].originalname,
contentType: req.files[i].mimetype
})
const response = await axios.post("http://localhost:8080/api/image/images/create", body);

Display image on Angular 10, where image is uploaded using Multer on Node.js server

I am using MEAN stack for my web application. I am using Multer to store images in a artImages folder on Node.js server. This is post request uses Multer to upload images and store image paths with other data in MongoDB.
const storage = multer.diskStorage({
destination: (req, file, callBack) => {
callBack(null, 'artImages/paintings')
},
filename: (req, file, callBack) => {
callBack(null, `painting&${Date.now()}&${file.originalname}`)
}
})
var upload = multer({ storage: storage })
router.post('/', upload.array('artFileLocations'), function(req, res) {
var paintingFileDesitnations;
const files = req.files
if(!files) {
res.sendStatus(500)
} else {
(new Paintings({ 'paintingName': req.body.artName, 'paintingFileLocations': req.files })).save()
.then((info) => res.send(info))
.catch((error) => console.log(error));
}
});
Now I am making a get request to MongoDB which gives data and file paths. Now I want to send the data as well as their respective images stored on server back to Angular. I have written this for the same:
router.get('/', function(req, res) {
Paintings.find({})
.then(paintings => {
imagePath = path.resolve(<path>, paintings[0].paintingFileLocations[0].path)
fs.readFile(imagePath, 'utf8', function (err, data) {
if (err) {
console.log(err);
}
console.log('Data: ', data);
res.send(data);
});
})
.catch(error => console.log(error))
});
Here, the request never consoles error, I did console data which is obviously a lot of gibberish.
On Angular client this is the response where the status says 200 but the response is HttpErrorResponse. I don't understand what is happening.
HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://localhost:8080/api/paintings/getAll", ok: false, …}
error: {error: SyntaxError: Unexpected token � in JSON at position 0 at JSON.parse (<anonymous>) at XMLHtt…, text: "�PNG
↵↵
IHDR??���7sRGB���8…�$�I'O$vr�:�b�*FR�B#!0(�b&�x'6��IEND�B`�"}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message: "Http failure during parsing for http://localhost:8080/api/paintings/getAll"
name: "HttpErrorResponse"
ok: false
status: 200
statusText: "OK"
url: "http://localhost:8080/api/paintings/getAll"
__proto__: HttpResponseBase
Can someone help undertand and solve this problem? And give me an idea of how to display the image on Angular client? Have been stuck on this for days.
If you're using Angular's HttpClient, the default responseType is json - you might want to choose blob
responseType?: "arraybuffer" | "blob" | "text" | "json"
See the overloads of the HttpClient get request
The call would be something like:
return this.httpClient.get(url, {responseType:'blob'});

Multipart form data throwing error in express js

I have a express proxy server for angular application. From angular I am making post request to expressjs, there the same formData posting to backend and getting 500 as response.
app.post('/upload', upload.any(), (request, response) => {
const formData = new FormData({'file': request.file});
axios.post(loaderUrl + `/loads`, formData, {headers:formData.getHeaders()})
.then(resp => {
response.send(resp.data)
})
.catch(error => {
response.send(error);
});
});
Here request.file = {
fieldname: 'file',
originalname: 'Sample.xlsx',
encoding: '7bit',
mimetype: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
buffer: <Buffer 50 6d 6c 20 ... 46844 more bytes>,
size: 46894
}
Backend error log: "org.springframework.web.multipart.MultipartException: Current request is not a multipart request"
You need to pass the content-type header.
headers: {
Content-Type: multipart/form-data,
formData.getHeaders()
}
Backend error log: "org.springframework.web.multipart.MultipartException: Current request is not a multipart request"
The error above clearly states that the request you are sending to the server is not of the exact type that is required. The request should explicitly state its type i.e. Multipart.
You can achieve that by replacing this line of code
axios.post(loaderUrl + `/loads`, formData, {headers:formData.getHeaders()})
With
axios.post(loaderUrl + `/loads`, formData, {headers: {'Content-Type': 'multipart/form-data'}})

Sending pdf files to user from nodejs to reactjs

I have pdf documents stored in the file system on the server side.
I need to let the user download one of them when he/she clicks on download.
The problem is that I know how to send a file from NodeJS to browser but here the request will be made by a ReactJS axios request. So when I send a file, the response will go to react. How do I send that pdf file to the user? Do I access the file system directly using my front end code?
I get the following in the browser console when I log the response after I do res.sendFile(file_path) in NodeJS
How do I process this so that I can make the user download the pdf?
You can use file-saver to download the file. Below is the function I'm using for pdf download. (response.data is the Buffer that nodejs sends back as a response)
import FileSaver from 'file-saver';
...
_onPdfFetched() {
FileSaver.saveAs(
new Blob([response.data], { type: 'application/pdf' }),
`sample.pdf`
);
}
or you can just show pdf to the user
window.open(response.data, '_blank');
Edit
The axios call should be like this:
axios.get(url, {
responseType: 'arraybuffer',
headers: {
Accept: 'application/pdf',
},
});
Edit 2
The nodejs code should be like this:
router.post('/api/downloadfile',(req, res, next) => {
const src = fs.createReadStream('path to sample.pdf');
res.writeHead(200, {
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename=sample.pdf',
'Content-Transfer-Encoding': 'Binary'
});
src.pipe(res);
});

Sending a buffer in multipart/form-data POST request Node | Express | request

I have a buffer that I have taken from users uploaded image, that I then want to send on to another API in a multipart/form-data POST request.
I'm having issues however with the request object. I want to send a stream or buffer rather than accessing local server file system / creating temp files. I'm fairly new to the concept of streams.
I get the correct response from API sending
image_file: fs.createReadStream('image.png')
But when I try:
image_file: data // buffer
I get an error from the API saying I'm missing the image_file parameter.
Please help!
Docs for the API I'm using (Face++)
I'm using request to make the post request.
Here is my code in question:
app.post('/', (req, res) => {
const url = 'https://api-us.faceplusplus.com/facepp/v3/detect';
let data = [];
req.on('data', (chunk) => {
data.push(chunk)
})
req.on('end', (req, res) => {
data = Buffer.concat(data);
const formData = {
api_key: process.env.FACEPP_API_KEY,
api_secret: process.env.FACEPP_API_SECRET,
// image_file: fs.createReadStream('image.png') // works
image_file: data // doesnt work
}
const options = {
uri: url,
method: 'POST',
formData
}
request(options, (err, response, body) => {
if (err) console.log(err)
console.log(body)
})
})
})
After a little playing about, I have the following code, it's working nicely for me. I used the Multer middleware (https://github.com/expressjs/multer) for the original multipart upload. As a matter of interest, request doesn't seem to play nice uploading files unless you specify a filename option.
const multer = require('multer');
const upload = multer();
app.post('/', upload.any(), (req, res) => {
const url = 'https://api-us.faceplusplus.com/facepp/v3/detect';
console.log('Image upload complete, creating request to: ' + url);
var formData = {
api_key: process.env.FACEPP_API_KEY,
api_secret: process.env.FACEPP_API_SECRET,
image_file: {
value: req.files[0].buffer, // Upload the first file in the multi-part post
options: {
filename: 'image_file'
}
}
};
const options = {
uri: url,
formData: formData,
method: 'POST'
}
request(options, (err, response, body) => {
console.log('Request complete');
if (err) console.log('Request err: ', err);
console.log(body)
})
})
I'm getting a response that looks like this:
{
"image_id": "GuF0MUPoaTcL/rbbcg+2kA==",
"request_id": "1520789753,d913cce4-118e-4893-a1ee-d1ace2b6a65b",
"time_used": 142,
"faces": [{
"face_rectangle": {
"width": 183,
"top": 125,
"left": 220,
"height": 183
},
"face_token": "8b8e327edfc10730f344b1465934a478"
}]
}
I tested the image upload to my local server using curl like so:
curl -v -i -F "data=#smiling_woman.jpg" -H "Content-Type: multipart/form-data" -X POST http://localhost:3000/

Resources