Vuejs load image from nodejs res.sendFile - node.js

In my vue's created, I use axios to connect to my server to retrieve an image as below:
created() {
this.schoolID = localStorage.getItem('schoolID')
console.log(this.schoolID)
axios.get(process.env.MY_URL + '/public/logo', {
params: {
schoolID: this.schoolID
}
})
.then(response => {
this.logo = response.data
console.log(this.logo)
})
.catch(e => {
console.log(e.response)
this.errors.push(e)
})
},
and my nodejs will receive the request and send the response like below
router.get('/logo', function(req, res){
School.findOne({ _id: mongoose.mongo.ObjectId(req.query.schoolID) }).exec().then(function (data) {
if (!data){
console.log("error... no logo found for the given id: " + req.query.schoolID)
return res.status(200).send({success: false, msg: 'No logo found.'});
}else{
res.sendFile(__dirname + '/uploads/' + data.logo);
}
});
});
my image should be loaded into my code
<img :src="this.logo">
I'm positive I got (at least the nodejs) the image file correctly because if I just append some string at the end of data.logo, I will get 404 not found error in my Vue and ENOENT: no such file or directory, stat 'D:\web\musleh-api\uploads\1542208727664_logo_sdam.png' error in my nodejs
However, no image is being loaded,and my console.log(this.logo) will display funny symbols which I assume is the image file if we try to open it using any text editor.
What did I miss?

I believe what you need to do is this in your HTML code, assuming that your image is base64 encoded:
<img alt="Awesome logo" :src="'data:image/png;base64,'+this.logo" />
Here is the source
Addition, as above seems not to work:
After some research I think we are not completely on the wrong path here, but give this a try:
On the NodeJS side try this:
}else{
var img = fs.readFile('__dirname + '/uploads/' + data.logo', function (err, data) {
var contentType = 'image/png';
var base64 = Buffer.from(data).toString('base64');
base64='data:image/png;base64,'+base64;
res.send(base64);
});
});
});
then in VueJS as before:
<img alt="Awesome logo" :src="this.logo" />
OR THE EASY WAY:
On the NodeJS side try this:
}else{
// prefix your domain if your API serves to other domains
res.send('/uploads/' + data.logo');
});
});
});
Also here Vuejs code remains as you did it.

Assuming that you want to pass the school ID to request the image, you don't need axios to make the request, you can use directly the <img src> tag with a dynamic parameter to request the data. You also need to change you express configuration to return the image with Content-Type:'image/png' or whatever is the mime type of your data.
Then on vue template you will need to pass the school id to the dynamic route, the data request and handling will be done by the img element
<img :src="`/logo/${schoolID}">
.
router.get('/logo/:schoolID', function(req, res){
School.findOne({ _id: mongoose.mongo.ObjectId(req.params.schoolID) }).exec().then(function (data) {
if (!data){
console.log("error... no logo found for the given id: " + req.params.schoolID)
return res.status(200)
.send({success: false, msg: 'No logo found.'});
}else{
res.type('png')
.sendFile(__dirname + '/uploads/' + data.logo);
}
});
});

Related

How to Send Image , Pdf and Few Parameters together From Angular to Node.Js Server

I am using Angular Material For getting Position of Draggable Image , getting input type file(pdf) from User and Images Stored in ./assets/emojis/. I am able to send Pdf from Angular to Node using ng2-file-upload and multer.
FrontEnd
<input (change)="onFileSelected()" ng2FileSelect [uploader]="uploader" type="file" id="file">
<ion-button class="input-group-text upload" (click)="uploader.uploadAll()" >Upload</ion-button>
Backend
app.post('/api/upload', upload.single('pdf'), function (req, res) {
console.log('File is available!');
return res.send({
success: true
})
});
Now i have image path selected by User at assets
imagePathToUpload:string = './assets/emojis/'+this.selectedEmoji
topPosition:number = this.topPos
leftPosition:number = this.leftPos
How can i send all these data together to Server , there is one way FormData but i dont understand how to use it.
Objective is Send Image , Pdf , left and top position to server. Any Advice would be Appreciated.
To send a file from Angular --> Nodejs is simple
Create upload method
FinalformData: FormData;
uploadFile(event) {
if (event.target.files && event.target.files.length > 0) {
const file = event.target.files[0];
this.FinalformData = new FormData();
this.FinalformData.append('file', file, file.name);
}
}
submit() {
// call your service and send it
this._sendfileService.sendFile(this.FinalformData)
.subscribe( res => {
if (res.success) {
console.log('file uploaded');
} else { console.log('faild uploading file'))}
})
}
all done now call your angular service with your http.post method here's and ex
sendFile(file: FormData): Observable<any> {
return this.http.post<any>(this.nodejsUrl, file);
}
to handle the file in backend look into multer https://www.npmjs.com/package/multer

Getting an image from localhost gives 404 with NodeJS and Express

I implemented an upload of images in NodeJS express using multer, and when I try to get the images in the browser I got this error:
URL: http://localhost:5500/images/posts/5e2843e4efa65f188fc5552f.png
Cannot GET /images/posts/5e2843e4efa65f188fc5552f.png
I saw in the console the 404 so I cannot get why I can not see my image.
I did the upload in this way:
postRouter.post(
"/:id/uploadImg",
multerConfig.single("image"),
async (req, res) => {
try {
const fileName =
req.params.id + path.extname(req.file.originalname);
const newImageLocation = path.join(
__dirname,
"../../images/posts",
fileName
);
await fs.writeFile(newImageLocation, req.file.buffer);
req.body.image =
req.protocol +
"://" +
req.get("host") +
"/images/posts/" +
fileName;
const newPostImg = await Posts.findOneAndUpdate(
{ _id: req.params.id },
{
$set: { image: req.body.image }
}
);
newPostImg.save();
res.send("Image URL updated");
} catch (ex) {
res.status(500).send({ Message: "Internal server error", err: ex });
}
}
);
And in my server.js
server.use(express.static("./images"));
I'm able to upload but then not able to see it and cannot figure out what is the issue.
When you wrote server.use(express.static("./images")); you told your server to search for dir's and files starting from the ìmages folder on your app.
Therefore you should go to http://localhost:5500/posts/5e2843e4efa65f188fc5552f.png to search for your uploaded file. Assuming there's no other matching route before server.use(express.static("./images"));.
EDIT:
If you want to be able to use the path you are already using, you should change your images directory like this:
--images
--images
--posts
-photo.png
And change the path where your multer code saves the file like this:
const newImageLocation = path.join(
__dirname,
"../../images/images/posts",
fileName
);

how process response object from Google Places API - placesPhoto

I am writing a simple wrapper in node.js which calls Goole Places API and gets a photo using photo_reference. When I run this and process the request from Postman it works but does not display photo itself. In the code below mapsClient.placesPhoto does return a huge response with many tags. Its not just raw image data. My question is how do I extract image or image data from googleResp object and send it back to client?
var googleMapsClient = require('#google/maps').createClient({
key: 'xyz'
});
app.post('/getGooglePlacePhoto/:photoref', function(req, res){
googleMapsClient.placesPhoto({
photoreference: req.params["photoref"],
maxwidth: 70,
maxheight: 70
}, function(err, googleResp){
if (!err) {
debug('got response from google');
res.set('Content-Type','image/jpeg');
debug(googleResp.body);
res.send(200, googleResp.body);
} else {
debug(err);
res.send(409, err);
return;
}
});
});

show image which is served by express in nodejs

I serve image from local hard drive in node express using sendfile like :
app.get('/data/getImage/:Id', function (req, res) {
console.log(req.params.Id);
res.sendfile('C:\\defaultimg.png', function(error){
if(error)
console.log(error.message);
else
console.log('File transferd successfully.');
})
});
and I call this method in angular and get data like:
var resource = $resource('/data/getImage/:id', {id: '#id'}, {getImage: {method: 'GET', isArray: false}});
resource.get({id: _id}, function (image) {
console.log('getImageById');
console.log(image);
callback(image);
});
so, my question is how i can i show this received data in image tag ?
thanks
Save the image path some where on your scope and then use ng-src.
<img ng-src="{{scopePropertyWithImageUrl}}" />
Link to the documentation: ng-src.

mongodb gridfs encoding picture base64

i try to readout an image, saved in mongodb, via gridfs (without temporary file)
it should be directly sent to ajax, which injects it into html
when i use my actual functions a large bit string is formed and sent to client (is saved in ajax response var)
but as it reaches the client, the bits arent correct anymore
so i look for a way to encode the picture before it is sent (into base64)
(or is there any other way?)
Serverside - javascript, gridfs
exports.readFileFromDB = function(req, res, profile, filename, callback){
console.log('Find data from Profile ' + JSON.stringify(profile));
var GridReader = new GridStore(db, filename,"r");
GridReader.open(function(err, gs) {
var streamFile = gs.stream(true);
streamFile.on("end", function(){
});
// Pipe out the data
streamFile.pipe(res);
GridReader.close(function(err, result) {
});
Clientside - javascript ajax call:
function imgUpload(){
var thumb = $("#previewPic");
$('#uploadForm').ajaxSubmit({
beforeSend:function(){
//launchpreloader();
},
error: function(xhr) {
//status('Error: ' + xhr.status);
},
success: function(response) {
console.log(response);
var imageData = $.base64Encode(response);
console.log(imageData);
thumb.attr("src","data:image/png;base64"+imageData);
$("#spanFileName").html("File Uploaded")
}
});
}
I'm doing something similar for a current project, but when the upload is complete, I return a JSON object containing the URL for the uploaded image:
{ success : true, url : '/uploads/GRIDFSID/filename.ext' }
I have a route in Express that handles the /uploads route to retrieve the file from GridFS and stream it back to the client, so I can use the above URL in an IMG SRC. This is effectively what appears in the DOM:
<img src="/uploads/GRIDFSID/filename.ext">
The route handler looks something like this (it uses node-mime and gridfs-stream):
app.get(/^\/uploads\/([a-f0-9]+)\/(.*)$/, function(req, res) {
var id = req.params[0];
var filename = req.params[1];
// Set correct content type.
res.set('Content-type', mime.lookup(filename));
// Find GridFS file by id and pipe it to the response stream.
gridfs
.createReadStream({ _id : id })
.on('error', function(err) {
res.send(404); // or 500
})
.pipe(res);
});
It obviously depends on your exact setup if my solution works for you.

Resources