import {Directive, OnInit, Input} from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import {HttpClient} from '@angular/common/http';
import { DomSanitizer, } from '@angular/platform-browser';
import { environment } from 'environments/environment';
import { Logger } from "angular2-logger/core";
/**
* Usage:
*
* <img [image-loader]="object.id" [file]="file" imageType="VENDOR_PROFILE" />
*/
@Directive({
selector: '[image-loader]',
host: {
'[src]': 'sanitizer.bypassSecurityTrustUrl(imageData)'
}
})
export class ImageLoaderDirective implements OnInit {
url: string;
apiUrl: string
imageData: any;
@Input('image-loader') vendorId: number;
@Input('imageType') imageType: string;
constructor(private http: HttpClient, private sanitizer: DomSanitizer, private logger: Logger) {
this.apiUrl = environment.apiUrl;
}
ngOnInit() {
this.imageData = 'assets/images/missing-image.jpg';
if (this.vendorId && this.imageType) {
if (this.imageType == 'VENDOR_PROFILE') {
this.url = environment.imageType[this.imageType].replace("{id}", "" + this.vendorId);
}
this.url = this.apiUrl + this.url
this.http.get<any>(this.url)
.subscribe(
data => {
let mimeType = data.mimeType;
this.imageData = 'data:' + mimeType + ';base64,' + data.imageContent;
},
(err: HttpErrorResponse) => {
if (err.status != 200) {
if (this.imageType == 'VENDOR_PROFILE') {
this.imageData = 'assets/images/missing-vendor-profile.jpg';
} else {
this.imageData = 'assets/images/missing-image.jpg';
}
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.log('Error fetching image:', err.error.message);
} else {
// normally this happens if the object returned is not of json format
// this can cause quite the trouble
console.log(`Error fetching image: code=${err.status}, message=${err.error}`);
}
}
}
);
}
}
}
The last method accepts the object id, and use it to query the object that contains the filename of the image. We get the image path and convert it to byte[] using Base64 class. Note that we use a dto to store the byte[] and mimeType, this will let us return the information as json, instead of just returning a byte[], which often caused problem. Also note that we send the mimeType, we need it when displaying the image.
// rest interface
@GET
@Path("/{id}/profileImage")
Response profileImage(@PathParam("id") Long id);
// implementing rest class
@Override
public Response profileImage(Long id) {
Response.ResponseBuilder responseBuilder = null;
try {
responseBuilder = Response.ok();
responseBuilder.entity(vendorApi.profileImage(id, httpServletResponse));
} catch (Exception e) {
responseBuilder = processException(e);
}
Response response = responseBuilder.build();
log.debug("RESPONSE={}", response.getEntity());
return response;
}
// get the image
public ImageDto profileImage(Long id, HttpServletResponse response) {
Vendor vendor = vendorRepository.findById(id);
if (vendor == null || StringUtils.isBlank(vendor.getProfileImageFile())) {
throw new EntityDoesNotExistsException(Vendor.class, id);
}
File file = new File(getAppRootDir() + File.separator + id + File.separator + vendor.getProfileImageFile());
if (!file.exists()) {
throw new FileDoesNotExistsException("File does not exists: " + file.getPath());
}
try {
String encodeImage = Base64.getEncoder().withoutPadding().encodeToString(Files.readAllBytes(file.toPath()));
ImageDto imageDto = new ImageDto();
imageDto.setImageContent(encodeImage);
imageDto.setMimeType(ImageUtils.probeMimeType(file));
return imageDto;
} catch (IOException e) {
throw new BusinessApiException("Error fetching file: " + file.getName() + ". " + e.getMessage());
}
}