Angular 5, как отобразить строку в кодировке base64 в формате jpeg - PullRequest
0 голосов
/ 25 сентября 2018

Я пытаюсь отобразить строку в кодировке base64 в формате jpeg.На сервере (C #) я просто возвращаю закодированную строку (просто жесткое кодирование для целей тестирования, игнорируя переданный параметр):

    [HttpGet("[action]")]
    public string GetImage(string imageInfo)
    {
        // get the path to the image, using the passed imageInfo
        var imgPath = @"C:\SmallFiles\TestLogo.jpg";

        // return base64 string
        byte[] imageArray = System.IO.File.ReadAllBytes(imgPath);
        string base64ImageRepresentation = Convert.ToBase64String(imageArray);
        return base64ImageRepresentation;

    }

Когда я беру эту строку (base64ImageRepresentation) и вставляю ее впреобразователь text-jpeg (https://onlinejpgtools.com/convert-base64-to-jpg), изображение отображается правильно, и закодированная строка начинается с этого: "/ 9j / 4". И я могу убедиться, что это на самом деле возвращается в браузер, используяВкладка Chrome Network.

Теперь, вот мой компонент Angular 5:

@Component({
selector: 'app-home',
templateUrl: './home.component.html',
})
export class HomeComponent {
  baseUrl: string;

  sanitizedImageSrc: SafeResourceUrl;

  constructor(private route: ActivatedRoute, private _http: HttpClient, @Inject('BASE_URL') baseUrl: string, private _sanitizer: DomSanitizer) {
this.baseUrl = baseUrl;
}


ngOnInit() {
// if image information is being passed to the page, get the parameter information
let imageLookupInfo = this.route.snapshot.queryParamMap.get('imgInfo');

if (imageLookupInfo)
  this.getImage(imageLookupInfo).subscribe(
    data => {
      this.createImageFromBlob(data);
    },
    error => console.error(error));
}

createImageFromBlob(image: Blob) {
    let reader = new FileReader();

    reader.addEventListener("load", () => {
      let result = reader.result;
      let imgString = result.toString().replace('text/plain', 'image/jpeg');
      this.sanitizedImageSrc = this._sanitizer.bypassSecurityTrustResourceUrl(imgString);
    }, false);

    if (image) {
      reader.readAsDataURL(image);
    }
}

getImage(imageLookupInfo: string): Observable<Blob> {
    return this._http.get(this.baseUrl + 'api/SampleData/GetImage?imageInfo=' + imageLookupInfo, { responseType: "blob" });    
  }
}

И мой HTML:

<div class='row'>
  <div class='col-lg-10 col-md-10 col-sm-10 col-xs-10'>
    <h1>Test Image Display</h1>
    <div *ngIf="sanitizedImageSrc">
      <img  [src]="sanitizedImageSrc" width="100" height="50">
    </div>    
  </div>
</div>

В методе createImageFromBlob я обнаружил, чтоimage Blob всегда имеет тип «text / plain»: Blob(26544) {size: 26544, type: "text/plain"}

Свойство type доступно только для чтения, поэтому я не могу его изменить. Вместо этого я жду, пока BLOB-объект преобразуется в строку черезМетод FileReader «readAsDataURL», а затем я делаю замену на «image / jpeg» (пожалуйста, дайте мне знать, если есть лучший способ), который дает мне imgString, которая начинается так:

"data:image/jpeg;base64,LzlqLzRBQVFTa1pKUmdBQkFRRUF"

Обратите внимание, как данные теперь начинаются с "Lzlq "а не" / 9j / 4 ".С чего бы это ???И когда я копирую полный текст закодированных данных и вставляю его в тот же конвертер текста в JPEG (https://onlinejpgtools.com/convert-base64-to-jpg),, я вообще не вижу изображения, которое именно то, что показано на моей веб-странице - вообще ничегоНет ошибок, просто нет изображения.

Что я делаю не так? Что здесь происходит? Кажется, это должно быть так просто. У кого-нибудь есть рабочий пример того, как это сделать?

Любая помощь будет наиболее ценной.

Спасибо, - Джон

ОБНОВЛЕНИЕ : я сделал эту работу со строкой в ​​кодировке base64 следующим образом. Это делает не ответьте на вопрос, почему подход Blob не сработал для меня, и я все еще хотел бы знать, но этот подход сработал для меня, если кто-то сочтет его полезным.

1) Измените сторону сервера так, чтобы она возвращала объект ImageInfo, определенный следующим образом:

public class ImageInfo
{
    public string FileExtension { get; set; }
    public string Base64EncodedContent { get; set; }
}

Таким образом, код на стороне сервера теперь выглядит следующим образом:

    [HttpGet("[action]")]
    public ImageInfo GetImageInfo(string imageInfo)
    {
        // get the path to the image, using the passed imageInfo
        var imgPath = @"C:\SmallFiles\TestLogo.jpg";

        // get image as base64 string
        byte[] imageArray = System.IO.File.ReadAllBytes(imgPath);
        string base64ImageRepresentation = Convert.ToBase64String(imageArray);

        var info = new ImageInfo();
        info.FileExtension = "jpeg";
        info.Base64EncodedContent = base64ImageRepresentation;

        return info;
    }

Затем угловой компонент изменяется напросто используйте два свойства возвращаемого объекта, определитеned в этом интерфейсе:

export interface ImageInfo {
    fileExtension: string;
    base64EncodedContent: string;
}

И компонент выглядит следующим образом (просто подтверждение концепции кода, а не реализация, достойная производства):

import { Component, Inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

import { ImageInfo } from '../interfaces/imageInfo';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
})
export class HomeComponent {
  baseUrl: string;
  sanitizedImageSrc: SafeResourceUrl;

  constructor(private route: ActivatedRoute, private _http: HttpClient, @Inject('BASE_URL') baseUrl: string, private _sanitizer: DomSanitizer) {
    this.baseUrl = baseUrl;
  }


  ngOnInit() {
    // if image information is being passed to the page, get the parameter information
    let imageLookupInfo = this.route.snapshot.queryParamMap.get('imgInfo');

    if (imageLookupInfo)
      this.getImageInfo(imageLookupInfo)
        .subscribe(
          imageInfo => {
            this.sanitizedImageSrc = this._sanitizer.bypassSecurityTrustResourceUrl('data:image/' + imageInfo.fileExtension + ';base64,' + imageInfo.base64EncodedContent);
            },
          error => console.error(error)
        );
  }

  getImageInfo(imageLookupInfo: string): Observable<ImageInfo> {
    return this._http.get<ImageInfo>(this.baseUrl + 'api/SampleData/GetImageInfo?imageInfo=' + imageLookupInfo);
  }
}

1 Ответ

0 голосов
/ 25 сентября 2018

лучший способ - вернуть байт [] с сервера и использовать его, как показано ниже

getImage(imageId: string): Observable<ImageSource> {
    return this.http.get(`${dashboardImagesUrl}/${imageId}`, { responseType: 'blob', observe: 'response' }).map((response) => {
      if (response) {
        const headers = response.headers;
        const blob = new Blob([response.body], { type: headers.get('content-type') });
        const urlCreator = window.URL;

        return {
          width: Number(response.headers.get('X-Image-Width')),
          height: Number(response.headers.get('X-Image-Height')),
          backgroundImage: this._sanitizer.bypassSecurityTrustUrl(urlCreator.createObjectURL(blob))
        };
      }
    });
  }

HTML

<img [src]="imageSource?.backgroundImage">

установить высоту, ширину изображенияпоскольку заголовки с сервера

ниже серверного кода могут быть не полезны для вас, но для java-Spring люди ниже будут полезны

Java-бэкэнд

public class ImageEntity {

    @Id
    private String id;

    private byte[] imageByteArr;

    private int height;

    private int width;

    public static ImageEntity create(MultipartFile file) {
        try {
            final BufferedImage image = ImageIO.read(file.getInputStream());
            if(image == null) {
                log.error("Can't convert the file to a buffered image.");
                throw new ImageProcessingException();
            }
            final ImageEntity entity = new ImageEntity();
            entity.setImageByteArr(file.getBytes());
            entity.setHeight(image.getHeight());
            entity.setWidth(image.getWidth());
            return entity;
        } catch (IOException exp) {
            log.error("Exception while converting image file:", exp);
            throw new ImageProcessingException(exp);
        }
    }

}

контроллер

@RequestMapping(
            path = "/{id}",
            method = RequestMethod.GET,
            produces = { MediaType.IMAGE_PNG_VALUE, MediaType.IMAGE_JPEG_VALUE })
    public ResponseEntity<byte[]> get(@PathVariable String id) {
        final ImageEntity entity = this.repository.findById(id).get(); // i'm reading from mongodb
        final HttpHeaders headers = new HttpHeaders();
        headers.setCacheControl(CacheControl.noCache().getHeaderValue());
        headers.set(X_IMAGE_WIDTH_HEARDER, String.valueOf(entity.getWidth()));
        headers.set(X_IMAGE_HEIGHT_HEADER, String.valueOf(entity.getHeight()));
        return new ResponseEntity<>(entity.getImageByteArr(), headers, HttpStatus.OK);
    }

при сохранении просто используйте

this.repository.save(ImageEntity.create(file));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...