The scenario is simple. Use a form to upload an image and if it is successfully uploaded, refresh a photogallery. I use angular6 and ng-carousel. All the system is locally set in my windows 10 laptop.
The form gets uploaded, the text data are saved on the database and the image is saved in a file in node 8.11.1. I save the image in the src/assets/images
. I can see the changes and I get no errors while uploading.
But, after the upload, I try to use the URL of the new image to add it as the last image in the carousel and all I get is a 404 error. The URL is like http://localhost:4200/assets/images/unsplash.jpg
The URL is valid, the image is there and all the other carousel images use the same URL. But, the new image has a 404 error. I have to recompile the angular app to see the image. Not just refresh the page, recompile the whole app.
I dont know how to fix this. I tried using a File object or the HTML5 FileReader API on the front end and not depend on creating a URL after image upload. But they dont have a URL and the ng-carousel needs a URL like /assets/images/img.jpg
to work. In order to use some kind of URL, I also tried to get the temporary URL from node and return it back to the front-end, but since it is a temp
folder URL, browser wont let me use it. I also tried to use createObjectURL
but is not supported in all browsers. I also tried to perform a GET
after the image is saved and get all the images names from the database, to loop them again and feed the carousel template once again. Nothing. Still a 404 error. I have to recompile the app.
What is happening? Is this a angular 6 issue? Security restriction? Please help me fix this, I dont know how to deal with it anymore.
Outline of code.
the form
<form *ngIf="pointPartsActive" [formGroup]="imageUpload" (ngSubmit)="imageUploadSubmitted($event.target)" >
<input type="file" (change)='imageChange($event)' #imageInput id="imageInput" name = 'imageInput' accept=".png, .jpg, .jpeg, .gif" formControlName="imageInput" >
<input type="text" formControlName="imageName" name='imageName' placeholder="name" >
<button type="submit" >Submit</button>
</form>
html carousel template, add custom html to also delete an image on the spot.
<ngb-carousel #carousel *ngIf="images" (slide)="onSlide($event)">
<ng-template ngbSlide *ngFor="let im of images; let i = index" id="{{im.id}}">
<img src='../assets/images/{{im.name}}' >
<div class='carousel-img-details'>
<button type="button" (click)='deletepic(im.photoId)'>delete</button>
</div>
</ng-template>
</ngb-carousel>
form submit
imageUploadSubmitted(form){
let formData = new FormData(form);
let eb =null;
this.http.post('http://localhost:3000/cms/upload',formData,{reportProgress:true,observe:'events'}).subscribe(
event=>{
if(event.type === HttpEventType.Response){
eb = event.body;
if(eb.success){
this.imageUpload.reset();
this.addpic(eb.data);
}
}
});
}
after successful form submit, update the array that feeds the carousel. Its a simple array of json objects like [{'id':1,'name':'James'},{'id':2,'name':'Nolan'}]
and feeds the carousel via ngFor
.
addpic(data){
let slide = null;
this.images.push({
'photoId':Number(data.id)
'id': this.images.length,
'name': data.name
});
//get the id of the last slide and go there :
setTimeout(() => {
slide = this.images[this.images.length-1].id;
this.carousel.select(slide);
});
this.images = this.images.slice(); //try to "refresh" array itself
}
The code logic in stackblitz
Thanks
This might be a solution for you:
For a live application you probably would want to save your images on a fileserver (for. example AWS S3 on Amazon AWS), and store the link to this file in a database.
For your localhost project you can use http-server to function as this fileserver or you can use the express framework with ur node application.
Then you must save the link to your file, either in a db (database) or inn a textfile. For this I would recomend that you setup a local MongoDB database. This might take some time for you to get into, but it is good learning experience. You can use https://mongoosejs.com/ to communicate with your node application.
Then when you upload a new image, you send it from your frontend Angular app, to your backend node/express application, save the file in the folder and save the link in the db. With the https-server you will be able to access the image right away (with maybe som delay). And with the links stored in the db you can send the data in the db to your front end with a http get request whenever you refresh your application.
I hope this will help you to reach your goal :)