【问题标题】:Angular Observable for PDFJS metadata extraction用于 PDFJS 元数据提取的 Angular Observable
【发布时间】:2020-08-25 22:03:09
【问题描述】:

我正在尝试使用 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 一直未定义。

我做错了什么?

提前感谢您的帮助!

【问题讨论】:

    标签: angular pdfjs-dist


    【解决方案1】:

    您可以使用 RxJS from 函数将 promise 转换为 observable,而不是手动创建 observable。从那里您可以应用任何 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;
        });
      };
    }
    

    【讨论】:

    • 谢谢。看起来应该指定地图中元数据的类型,否则它会抱怨不知道“信息”位。 (“未知”类型上不存在属性“信息”。)。你知道那是什么类型的吗?
    • 这很可能是 TS Lint 错误。尽管如此,代码应该可以正常工作。它显示了该错误,因为 Linter 不知道来自 getMetadata() 调用的响应的属性。您可以通过使用括号表示法而不是点表示法来访问属性来快速修复它。我已经更新了答案。另一种方法是为来自getMetadata() 函数的响应签名定义一个接口,并定义metadata 变量的类型。
    猜你喜欢
    • 1970-01-01
    • 2020-08-26
    • 2017-04-17
    • 1970-01-01
    • 2019-10-15
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多