Get image after it is uploaded using angular and node - node.js

I have a simple reactive form in angular 6 that it also has a file input to upload images.
The scenario is to submit the form, save the image and the text fields of the form and then update a photo gallery with the new image. For a photo gallery, I use the ng carousel.
This is the code in the front-end
<form [formGroup]="myForm" (ngSubmit)="submitForm($event.target)" >
<input type="file" (change)='imageChange($event)' formControlName="imageInput" name = 'imageInput'>
<input type="text" formControlName="imageName" name='imageName'>
<button type="submit" >Submit</button>
</form>
save it like
submitForm(form){
let formData = new FormData(form);
this.http.post('http://localhost:3000/cms/upload',formData,{reportProgress:true,observe:'events'}).subscribe(
event=>{
if(event.type === HttpEventType.Response){
eb = event.body;
this.addpic(eb.data);
}
});
}
eb.data contains data that came from the server, after successfully saving the form data, the id of the new image and its file name.
In addpic I try to add a new image in the carousel. Add all the new data to an array, so I can use the array later, to ngFor it and dynamically create the ng Carousel
addpic(data){
this.images.push({
'id': data.id,
'name': data.name
});
}
use it like so
<ngb-carousel #carousel *ngIf="images" >
<ng-template ngbSlide *ngFor="let im of images; let i = index" id="{{im.id}}">
<img src='../assets/images{{im.newName}}' >
</ng-template>
</ngb-carousel>
So this works fine, but the image is never rendered. I get no errors, I see all the data saved in my database, the image is transferred in the folder as it should, but no new image in the carousel, just a 404 error in the console. The images array is updated, but no image in the carousel. The URL is ok, all the other images with the same URL are rendered in the carousel. It's like the app had no time to see the whole update, so it cannot show the image.
I tried to grab the image file object from the form, save it in angular in a selectedFile: File; and use this in the carousel, but this has no path or anything similar. Grab it when it is set in the form
imageChange(e){
this.selectedFile = e.target.files[0];
}
and use it in addpic
addpic(data){
this.images.push({
'id': data.id,
'name': this.selectedFile.path
});
}
I also tried to use the formData before the form submission, t get the image, but the result is the same, an object with no path.
I also tried to "read" the file using HTML5 FileReader, but this is an image and in the carousel, I need to provide a URL for the src, not just the image file.
I also used formidable in the node to parse the form and take the path of the image, return it back in the front-end along with the id and the file name and use that as an src. But this won't be used by the browser for security reasons I guess, because it is a URL in the temp files.
I also tried to get all the images from the server with a query, but the new image is still not available, giving a 404 error, even though the image is in the folder and the database is updated.
like this
addpic(data){
this.getImages(this.currentId); //get all images again
this.images.push({
'id': this.images.id,
'name': this.images.path
});
}
I have to refresh the page for the image to show. I don't know how to fix this. Any ideas? Is it a security issue that I cannot get the image right away, even though it is saved and I have to refresh? I would like to avoid performing an extra get, if it is possible, to keep client-server communication minimum.
I use angular6 and node 8.11. in windows 10, all locally in my laptop.
Thanks

Might be issue related to updated variable refers to same reference. inside addPic(). add this line of code as last line.
this.images = this.images.slice();

Related

Can I store textarea containing images in mongo db?

I am creating a personal blog using node js and mongo db and implementing the function of writing posts.
I thought that the title and description of the post could be saved in the mongo db in String format, but I am curious about how to save the elements such as the image of the textarea and the font size.
I used tinyMCE as a text editor to write the content and the code is as follows.
<form action="/articles" method = "POST">
<h4>title</h4>
<input required type="text" name = "title" / class='form-control'><br>
<h4>description</h4>
<textarea name="description" class = 'form-control'></textarea><br>
<h4>contents</h4>
<textarea id="mytextarea" name="contents" rows = '10'></textarea>
취소<button type = "submit" class="btn btn-primary">저장</button>
</form>
And an example of a post is as follows.
I am wondering how can I save the contents of a textarea containing a picture in a db.
You can refer to this question here.
However, in terms of scalability I do not recommend uploading pictures to mongoDB. It will take way too much space. What I would do is the following:
Create a bucket on AWS s3 or something similar.
Connect your nodes.js server to the newly created bucket using multer in combination with the aws-sdk. (good example here )
Once uploaded the bucket will create a link to the image.
Save the image link on mongoDB.
This way you only store the link, which makes the project a lot more scalable.

How to transit another ejs file in Node.js

When I develop ejs file, I would like to transit to another ejs by clicking button.
But when I try to click and trnasit to quiz.ejs,nothing happend.
Are there any wrong point in ejs ?
And how to fix them?
Thanks
following is a part of my ejs file.
<button onclick = "href = '/quiz'">start</button>
And following is my Router.
router.get('/quiz',(req,res)=>{
res.render(Views+'quiz.ejs');
});
following is a part of my app.js
app.use('/quiz',Router);
Firstly you don't transit to any ejs file. You transit to another route which renders an ejs file.
So all you need to do is
Create a ejs file, lets say 'quiz.ejs'
Add a route to render this -
router.get('/quiz',(req,res)=>{
res.render('quiz');
});
And then finally redirect the user to quiz route.
<a "href = '/quiz'>To Quiz</button>
Also note that you need <a> anchor tag to navigate not a button.

Is it possible to render binary images data store in mongoDB to handlebars template?

I´m looking for some help. I´m creating a gallery application using nodejs, mongoDB and handlebars template to show the gallery. Everything goes fine till I find all images in my mongoDB (stored as Binary Data) and try to render in my handlebar template. I'm trying this:
routes.js
router.get('/gallery', async (req, res) =>{
const pics = await Img.find();
console.log(pics); // No problems showing images as binary data and all fields in the Schema
res.render('images/gallery.hbs', {pics});
});
template.hbs
{{#each pics}}
<div class="row">
<img src='????'>
</div>
{{/each}}
where ???? is my big problem, I don't know what's the code to put there or if I'm using the right way.
Pls help. I'm newer on this
if you are storing binary you can be added to the src of course, but you should consider the metadata associated with the binary like this:
<img src="data:image/png;base64,...">
Note:
This is a bad practice by the way, and you should never save the images on the DB whatever the case, you can use external service like aws s3 and upload your images there and store their Uri instead, they're a lot of reasons for this the biggest one it gonna cost you a lot of money -_-

base64 images not displaying in Outlook when using ejs + emailjs

I'm using a mix of ejs and emailjs to send out emails in my node.js app when various events happen. I'd like to embed a base64 image (a small logo) into the email when it sends, but both Outlook and Gmail (plus Inbox by Google) fail to render the image.
I'm using this bit of code to find the mime type of the image and put together the base64 string:
MyApp.prototype.ImageToBase64 = function(image) {
var mime = require("mime")
file = fs.readFileSync(__dirname + "/images/" + image, { encoding: 'base64'})
return 'data:' + mime.lookup(image) + ';base64,' + file;
}
That works great, because I'm able to copy and paste that resulting string right into my browser and see the image. But when I send the email via emailjs, Outlook converts the +s to +. When I "View Original" in Gmail, the base64 is split up into 'chunks'. Each chunk is on a newline and each line ends with a =. If I take Gmail's version and remove the = and newline then paste it into my browser, the whole picture loads perfectly, but it just refuses to load anywhere else, regardless of whether the user is in my contact list or not.
Here's the code I'm using to send the email:
// Host, username, password and SSL (false) all set above here
server.send({
text: myTemplate,
from: "me#example.com",
to: "someone#example.com",
subject: "Testing",
attachment: [
{data:myTemplate, alternative:true}
]
})
And the template looks like this (truncated, as the other bits aren't important):
<body>
<p><img src="<%- ImageToBase64("logo.png") %>"></p>
<h1><%= Name %> has been triggered</h1>
<p><%= Name %> has been triggered. It was triggered on <%= TheDate %></p>
Any hints?
EDIT: I tried setting the headers in the "attachment" property, but with no luck
Outlook uses Word to render the images, and Word does not support embedded (src="data:image") images.
You need to attach the image as a file and set the Content-ID MIME header to the value matching the cid attribute on the image (<img src="cid:xyz">) in the HTML body.
Okay, so even though this answer is from 2013, it seems like the wisdom still holds true, in that base64 image support sucks in email clients.
Basically the only mail clients that still support inline images are either older ones (e.g. Office 2007), or Apple / Android's default mail apps.
While that's a bit disappointing, it's not the end of the world, as the email will only be seen by people on the same network as my app, so I can just point to the image hosted on the web portion of the app.
But for anyone else trying this, host your image on an image sharing site like Imgur or on your own server and use a regular ol' <image> tag to display it.
So much for self-contained emails, right?

Display image in a packagedapp/extension after selecting from Google Drive

My packaged app gets images from google drive and then display them on the side. But I can't get the images to be displayed. I am trying to get the url of the image so that I can put that url in an image source. The image url that I am getting is actually an html page rather than jpeg, png etc. I have looked at the reference guide for google picker but nothing seems to work.
I am using this
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
fileName = data.docs[0].name;
imgURL = data.docs[0].url;
}
I want to use imgURL as the source for image selection but imgURL is not something like "https//:www.example.com/image.jpg. It is rather an html page I want something that ends with file type only then it will be able to display the image. Please let me know how can I get the image to be displayed in html page of my packaged app after selecting it from google drive.
You should fetch the metadata of the image, then use the webContentLink of the image, then the user can view it in a logged in browser. See the documentation on downloads for more information.

Resources