Angular Observable用于PDFJS元数据提取

问题描述

我正在尝试使用PDFJS从PDF提取元数据,并通过Observable订阅获取它。

服务代码

export interface PdfProperties {
  title: string;
  author: string;
  subject: string;
  keywords: string;
}

...

  extractPdfProperties(file: Uint8Array): any {
    const pdfPropertiesObservable = new Observable<PdfProperties>( (observer) => {

      const pdfLoading = pdfjsLib.getDocument(file);
      pdfLoading.promise.then( pdf => {
        pdf.getMetadata().then( Metadata => {
          this.pdfProperties.title = Metadata.info.Title;
          this.pdfProperties.author = Metadata.info.Author;
          this.pdfProperties.keywords = Metadata.info.Keywords;
          this.pdfProperties.subject = Metadata.info.Subject;
          observer.next(this.pdfProperties);
          return this.pdfProperties;
          });
        });
    });
    return pdfPropertiesObservable;
  }

组件代码

 onFileSelect(input: HTMLInputElement) {
    const fileReader = new FileReader();
    fileReader.readAsArrayBuffer(input.files[0]);
    fileReader.onload = () => {
      const typedArray = new Uint8Array(fileReader.result as Uint8Array);
      const pdfObservable$ = this.pdfProperties.extractPdfProperties(typedArray);
      pdfObservable$.subscribe((subscriptionpdfp: PdfProperties) => { this.pdfp = subscriptionpdfp; });

    };
  }

没有错误,但是this.pdfp一直未定义。

我在做什么错了?

在此先感谢您的帮助!

解决方法

您可以使用RxJS from函数将promise转换为可观察对象,而不是手动创建可观察对象。从那里,您可以应用任何RxJS运算符将响应通知转换为所需的表单。

我正在使用switchMap运算符将一个可观察对象映射到另一个,并使用map运算符将通知转换为实例类型为PdfProperties的对象。

尝试以下

export interface PdfProperties {
  title: string;
  author: string;
  subject: string;
  keywords: string;
}

extractPdfProperties(file: Uint8Array): Observable<PdfProperties> {    // <-- return an observable
  return from(pdfjsLib.getDocument(file).promise).pipe(   // <-- convert promise to an observable
    switchMap(pdf => from(pdf.getMetadata())),// <-- switch to `getMetadata()` promise
    map(metadata => ({                            // <-- map to object of interface type `PdfProperties`
      title: metadata['info']['Title'],author: metadata['info']['Author'],keywords: metadata['info']['Keywords'],subject: metadata['info']['Subject']
    } as PdfProperties))
  );
}

onFileSelect(input: HTMLInputElement) {
  const fileReader = new FileReader();
  fileReader.readAsArrayBuffer(input.files[0]);
  fileReader.onload = () => {
    const typedArray = new Uint8Array(fileReader.result as Uint8Array);
    this.pdfProperties.extractPdfProperties(typedArray).subscribe((subscriptionpdfp: PdfProperties) => {
      this.pdfp = subscriptionpdfp;
    });
  };
}