get image from backend api and display in angular - node.js

I want display image in angularV10 and get it from backend and I don't know why image not display and got error I'm looking for how to solve but I don't get answer
please can someone guide me
back-end:
get_image:async(req,res,next)=>{
Image.findAll().then(data=>{
res.send(data)
}) }
api:
router.get("/get_image",uploadController.get_image)
Front-end Angular : service.ts
get_file(): Observable<any>{
return this.http.get(baseUrl + '/get_image' , { responseType: 'Blob' as 'json' })}
code:
createImageFromBlob(image: Blob) {
let reader = new FileReader();
reader.addEventListener("load", () => {
this.imageToShow = reader.result; <<< this.imageToShow
}, false);
if (image) {
reader.readAsDataURL(image);
console.log(image)
}
}
get_image():void{
this.AddFileService.get_file().subscribe(data=>{
this.createImageFromBlob(data);
console.log(data)
})}
html:
<img [src]="imageToShow "/>
Error :
big error
unsafe:data:application/json;base64, ..... alot of chars i don't under stand

Not much in the way of detail to this, but hopefully I can at least clear some things up for you so that you can find your footing with the issue a little better.
The lot of characters you don't understand are the base64 encoded string of the image (if your code is producing an image, appropriately, at least).
What you want to show as an image is a data URI and it looks much like you've shown:
data:image/jpeg;base64,[a lot of characters]
Depending on the actual image type, it might not be image/jpeg, it might be image/png, etc.
There's two things wrong with that final block you've shown:
unsafe:data:application/json;base64, ..... alot of chars i don't under stand
The first one, having now told you what it should look like, is that it thinks the data is application/json instead of the expected image/xyz. So your process for constructing that data URI is wrong somewhere.
I suspect it's where you are telling in your blob type is supposed to be json (thus, application/json):
get_file(): Observable<any>{
return this.http.get(baseUrl + '/get_image' , { responseType: 'Blob' as 'json' })}
The second is the clue to the main issue that you are really seeing: unsafe:....
In order to display images in Angular in this fashion, you need to put those URIs and whatnot through the DomSanitizer:
constructor(private readonly sanitizer: DomSanitizer) {}
public safeImage: SafeUrl;
private getImage(...): void {
const imageBase64String = this.createImageFromBlobOrSomething(...);
this.safeImage = this.sanitizer.bypassSecurityTrustUrl(imageBase64String);
}
And your template will then use safeImage instead:
<img [src]="safeImage"/>
That will stop the unsafe:... error, but then you'll find that you won't see an image, because the data URI is for application/json, instead of an image type, which you'll need to go ahead and fix.
Edit: My approach for multiple images is to save the images (if you want to keep the initial images for further usage/manipulation) or just only save the safe url version of them...
this.rawImages = data; // Wherever your images come from, and if you want to keep them...
this.safeImages = [];
this.rawImages.forEach((img) => {
this.safeImages.push(this.sanitizer.bypassSecurityTrustUrl(img));
});
Then instead of *ngForing the raw images themselves, do it over the safeImages array instead:
<div *ngFor="let safeUrl of safeImages">
<img [src]="safeUrl">
</div>

ok anyone use blob for any file image pdf is not good decide
the best solution i do upload image to backend and generate URL
this website is helpful if you use node.js here

Related

Remix.run blog tutorial - optimistic UI

I'm following the blog tutorial on the remix.run example page and I'm struggling with the Optimistic UI aspect of it and failing to find any examples online
As you can see in my github repo I am trying to render the <PostAdmin /> route, but it's not loading for some reason.
import PostAdmin from "~/routes/posts/admin";
export default function NewPost() {
const errors = useActionData();
const transition = useTransition();
const isCreating = Boolean(transition.submission);
const title = transition?.submission?.formData?.get("title");
return isCreating ? (
<>
<PostAdmin />
</>
) : (
....
My original plan was to pass some additional items in here so I can render to the sidebar optimistically like the following. However I can't get the PostAdmin route to load at all, with the error Cannot destructure property 'posts' of 'useLoaderData(...)' as it is undefined.
export default function PostAdmin({
newPost,
}: {
newPost?: { title: string; slug: string };
}) {
As a side note, it's rendering the nested AdminIndex ok when I try that, but this would not achieve the homework example in the remix tasks as I need to pass it to the sidebar.
Hard one to explain and I imagine someone who's done the tasks before or has a solid example of Remix will understand. It may be that I am approaching this incorrectly. I have struggled to find complete examples anywhere.

In Angular, how to parse and extract HTTP response that has Complex structure (JSON)?

I am new to Angular and need your help here. I have an Angular service that has the API calling function as shown below.
searcheBay() {
console.log("calling ebay service");
return this.httpClient.get (this.ebayURL);
}
and I am calling this function from the component as shown below.
this.searchService.searcheBay().subscribe((data) => {
this.svcdata = data
});
The data variable has complex JSON structure (see the image below).
The data I am looking to read is held by "searchResult" element. Could you suggest how to parse and extract the "searchResult" element? Thanks in advance.
I debugged in the Safari DEV console and see the element accessibility as shown below.
When I updated the same code in my component, I encounter compile: ERROR in src/app/search/search.component.ts(20,29): error TS2339: Property 'findItemsByKeywordsResponse' does not exist on type 'Object'. Please suggest your thoughts.
serviceOnButtonClick(){
this.searchService.searcheBay().subscribe((data) => {
this.svcdata = data.findItemsByKeywordsResponse[0].searchResult
});
#javapedia.net try this, if you response data Object is same as you shown in the image,
this.searchService.searcheBay().subscribe((data) => {
this.svcdata = data.findItemsByKeywordsResponse[0].searchResult;
console.log(this.svcdata);
});
Edit
this.searchService.searcheBay().subscribe((data: any) => {
this.svcdata = data.findItemsByKeywordsResponse[0].searchResult;
console.log(this.svcdata);
});
I ended up using the map projection as shown below. Hope this helps.
serviceOnButtonClick(){
this.searchService.searcheBay().pipe(map((data:any) => data.findItemsByKeywordsResponse[0].searchResult)).subscribe((data) => {
this.svcdata = data;
console.log(this.svcdata);
});
}

Handling Promise and Observable on same variable in Node.js & Angular

In my project, I have an image.
On initialization; I load it from a Promise<string>; where string is a URL to the image
Then I use a node package to change and crop the image. It asks for an image, crops it to the requested size and returns an Observable<anObject> where the anObject.base64 is a base64 representation of the cropped image. It's contained in a dialog.
I tried many many things but could not change the image of the <img> tag automatically.
Here is my last setup:
image: Observable<string>;
...
ngOnInit() {
...
prd.images.big.then(img => {
this.image = of(img);
});
// prd.images.big is a Promise<string>
...
}
showImageDialog() {
this.image = this.imageDialog.openDialog().pipe(
map(data => {
return data.base64;
})
);
}
And my template:
....
<a style="cursor: pointer" (click)="showImageDialog();">
<img [src]="(image | async) || 'an url to default image'"/>
</a>
....
Weird thing is, image not change automatically, but when I click on the image again, it changes.
I hope any of you can help to achieve this. Thank you.
You want to avoid re-assigning the observable once you create it. Try something like this:
image: Subject<string>;
...
ngOnInit() {
this.image = new ReplaySubject<string>(1);
prd.images.big.then(img => this.image.next(img));
}
showImageDialog() {
this.imageDialog.openDialog().subscribe(data => {
const dataUrl = `data:image/jpeg;base64,${data.base64}`;
this.image.next(dataUrl);
});
}
FYI a Subject is just a variable that acts as both observer and observable-you can subscribe or pipe operations from it like any observable and you can also manually put values into the subject that will then be observed by all of the subscribers. In the code above I used a special kind of subject that will replay the most recent value to any late subscribers just in case you put a value in before the view has time to subscribe.
You are currently assigning a subscription to this.image. Instead, set this.image to be the data.base64 returned inside your map function. If you want to use base64-encoded image bytes for an image tag, you need to use a data URL
If your image type is jpeg:
<img src="data:image/jpeg;base64,{{image}}"/>

Pagination Ideas for Angular2 and ReactiveX

I'm learning ReactiveX. I've snipped the error checking, logging, and other bits out to make this easier to read.
I have a service that returns a collection of objects as JSON:
getPanels() {
return this.http.get(this._getPanelsUrl)
.map(panels => <Panel[]> panels.json());
}
My component calls the service method and stores the data in an array:
panels: Panel[] = [];
ngOnInit(){
this._PanelService.getPanels()
.subscribe(data => this.panels = data);
}
The goal is to display this data in groups in my template:
<ol>
<li *ngFor="#panel of panels">
<h3>{{panel.startDate}}</h3>
</li>
</ol>
Now I want to add pagination and display only three or four panels at a time.
My first idea was to use bufferCount to emit the objects in groups:
getPanels() {
return this.http.get(this._getPanelsUrl)
.map(panels => <Panel[]> panels.json())
.bufferCount(3,3);
}
Now I have a multidimensional array, so I have to update the component accordingly:
panels: Array<Panel[]> = [];
ngOnInit(){
this._PanelService.getPanels()
.subscribe( data => this.panels = data );
}
I thought I would have a nice and tidy array with each index having three members of the collection. I was wrong, and the entire collection is now stored in data[0]. Next, I tried switching the chain up a bit:
getNextPanel() {
return this.http.get(this._nextPanelUrl)
.bufferCount(3,3)
.map(res => <Panel[]> res.map(r => <Panel> r.json()));
}
Whoa. I obviously need someone to save me from myself at this point. Look at my lambdas! Data isn't even going to flow all the way back to the component at this point. This is when I started thinking maybe I don't need to learn how to do this the ReactiveX way … .
My next course was to try and iterate through the values with Angular. I tried using a few variables with the slice pipe:
<ol>
<li *ngFor="#panel of (panels | slice:start:items)">
<h3>{{panel.startDate}}
</li>
</ol>
<button (click)="start = start + start"></button>
Even though Angular 2 is still in beta, I could tell that I was getting tired when the parser kept barking at me for using operators and expressions where they don't belong.
I'm ready to learn from these mistakes so I can make bigger ones. Any suggestions?
[EDIT]
I've decided to use ng2-pagination because it does exactly what I want it to do. I'm not going to post that as the answer, however, because I still want to try and implement it with rxjs.
So if you've come this far, and you just need something that works, ng2-pagination (in beta 2 as of this writing) works very well.
Really late, but I hope this might help someone else with this issue.
I think the problem with your implementation is that you are overwriting the this.panel variable with each onNext event on the subscriber.
With this change should work as expected:
getPanels() {
return this.http.get(this._getPanelsUrl)
.map(panels => <Panel[]> panels.json())
.bufferCount(3)
.toArray();
}
and then:
panels: Panel[][] = [];
ngOnInit(){
this._PanelService.getPanels()
.subscribe( data => { this.panels = data } );
}
The idea is to merge all onNext events into an array (using the toArray method) that will be emited as the single onNext of that new Observer, and will contain all events.

The right pattern for returning pagination data with the ember-data RESTAdapter?

I'm displaying a list of articles in a page that are fetched using the Ember Data RESTAdapter. I need to implement a bootstrap'esque paginator (see: http://twitter.github.com/bootstrap/components.html#pagination) and cant seem to find a sane pattern for returning pagination data such as, page count, article count, current page, within a single request.
For example, I'd like the API to return something like:
{
articles: [{...}, {...}],
page: 3,
article_count: 4525,
per_page: 20
}
One idea was to add an App.Paginator DS.Model so the response could look like:
{
articles: [{...}, {...}],
paginator: {
page: 3,
article_count: 4525,
per_page: 20
}
}
But this seems like overkill to hack together for something so trivial. Has anyone solved this problem or found a particular pattern they like? Is there a simple way to manage the RESTAdapter mappings to account for scenarios such as this?
Try to use Ember Pagination Support Mixin and provide your own implementation of the following method. Instead of loading all the content, you can fetch the required content when the user is navigating the pages. All what you need initially is the total account of your records.
didRequestRange: function(rangeStart, rangeStop) {
var content = this.get('fullContent').slice(rangeStart, rangeStop);
this.replace(0, this.get('length'), content);
}
With ember-data-beta3 you can pass a meta-property in your result. The default RESTSerializer looks for that property and stores it.
You can access the meta-data like this:
var meta = this.get("store").metadataFor("post");
If you are not able to change the JSON returned from the server you could override the extractMeta-hook on the ApplicationSerializer (or any other Model-specific serializer).
App.ApplicationSerializer = DS.RESTSerializer.extend({
extractMeta: function(store, type, payload) {
if (payload && payload.total) {
store.metaForType(type, { total: payload.total }); // sets the metadata for "post"
delete payload.total; // keeps ember data from trying to parse "total" as a record
}
}
});
Read more about meta-data here

Resources