问题描述
我正在尝试使用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;
});
};
}