我试图从FileReader返回结果,但我发现了this实现。但由于它已经过时了,我想知道如何使用ES6 Promises或Rx Observables实现相同的功能。
下面是我引用上述链接的代码,它按预期工作。
import { Injectable } from '@angular/core';
import * as XLSX from 'xlsx';
import * as XLS from 'xlsx';
@Injectable()
export class ExcelReaderService {
constructor() { }
importFromExcel(ev): JQueryPromise<any> {
let deferred = $.Deferred();
let regex = /^([a-zA-Z0-9\s_\\.\-:])+(.xlsx|.xls)$/;
let workbook;
let excelInJSON;
if (regex.test(ev.target.files[0].name.toString().toLowerCase())) {
let xlsxflag = false; /*Flag for checking whether excel is .xls format or .xlsx format*/
if (ev.target.files[0].name.toString().toLowerCase().indexOf(".xlsx") > 0) {
xlsxflag = true;
}
let fileReader = new FileReader();
fileReader.onload = (ev) => {
let binary = "";
let bytes = new Uint8Array((<any>ev.target).result);
let length = bytes.byteLength;
for (let i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
/*Converts the excel data in to json*/
if (xlsxflag) {
workbook = XLSX.read(binary, { type: 'binary', cellDates: true, cellStyles: true });
// only first sheet
excelInJSON = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
deferred.resolve(excelInJSON);
}
else {
workbook = XLS.read(binary, { type: 'binary', cellDates: true, cellStyles: true });
excelInJSON = <{}[]>XLS.utils.sheet_to_row_object_array(workbook.Sheets[workbook.SheetNames[0]]);
deferred.resolve(excelInJSON);
}
}
// init read
if (xlsxflag)
fileReader.readAsArrayBuffer((<any>ev.target).files[0]);
else
fileReader.readAsBinaryString((<any>ev.target).files[0]);
} else {
deferred.reject('Invalid file!');
}
return deferred.promise();
}
}在消费者component中
this.excelReaderService.importFromExcel(ev).then((result) => {
this.detailHeadings = Object.keys(result[0]);
this.detailData = result;
})如果有人能帮我解决这个问题,那就太好了,因为我是异步编程的新手。
发布于 2018-02-15 16:25:36
我就是这么做的,以防有人想要一个能读取Excel文件的Angular服务,并以JSON格式的内容的observable作为响应。
我使用SheetJS读取文件并输出JSON。
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import * as XLSX from 'xlsx';
@Injectable()
export class ExcelReaderService {
constructor() { }
importFromExcel(ev): Observable<any> {
let workbook;
let excelInJSON;
const fileReader = new FileReader();
// init read
fileReader.readAsArrayBuffer((<any>ev.target).files[0]);
return Observable.create((observer: Subscriber<any[]>): void => {
// if success
fileReader.onload = ((ev: ProgressEvent): void => {
let binary = "";
let bytes = new Uint8Array((<any>ev.target).result);
let length = bytes.byteLength;
for (let i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
// Converts the excel data in to json
workbook = XLSX.read(binary, { type: 'binary', cellDates: true, cellStyles: true });
// only first sheet
excelInJSON = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
observer.next(excelInJSON);
observer.complete();
}
// if failed
fileReader.onerror = (error: FileReaderProgressEvent): void => {
observer.error(error);
}
});
}
}在component中,只需将如下所示的事件传递给此服务,它将使用JSON进行响应。
this.excelReaderService.importFromExcel(ev)
.subscribe((response: any[]): void => {
// do something with the response
});发布于 2017-10-01 22:18:56
正如在similar case中所显示的,为了避免延迟(反)模式,应该首先终止FileReader load事件:
let fileReader = new FileReader();
const fileReaderPromise = new Promise(resolve => fileReader.onload = resolve);
if (xlsxflag)
fileReader.readAsArrayBuffer((<any>ev.target).files[0]);
else
fileReader.readAsBinaryString((<any>ev.target).files[0]);
return fileReaderPromise.then(e => {
let excelInJSON;
...
return excelInJSON;
});也可以使用fromEvent将其转换为可观察对象
const fileReader$ = Observable.fromEvent(fileReader, 'load')
.map(e => ...)
.first();
if (xlsxflag)
fileReader.readAsArrayBuffer((<any>ev.target).files[0]);
else
fileReader.readAsBinaryString((<any>ev.target).files[0]);
...
return fileReader$;发布于 2019-05-10 23:48:03
在前面@karthikaruna的回答的基础上,我补充说,使用Observables,很容易让.pipe链从File对象返回您想要的内容:
(请注意,这些类型可能不是100%正确的)。
import { Injectable } from '@angular/core';
import { Observable, Subscriber } from 'rxjs';
import { map } from 'rxjs/operators';
import * as XLSX from 'xlsx';
@Injectable()
export class ExcelReaderService {
public importFromExcel(ev): Observable<any[]> {
return this.fileToString(ev.target.files[0])
.pipe(
// convert from file contents to Excel rows
map((binary: string): any[] => {
// Converts the excel data in to json
const workbook = XLSX.read(binary, { type: 'binary', cellDates: true, cellStyles: true });
// only first sheet
const excelInJSON = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
return excelInJSON;
}),
);
} // end importFromExcel()
private fileToString(file: File): Observable<string> {
return Observable.create(
(sub: Subscriber<string>): void => {
const r = new FileReader;
// if success
r.onload = (ev: ProgressEvent): void => {
sub.next((ev.target as any).result);
};
// if failed
r.onerror = (ev: FileReaderProgressEvent): void => {
sub.error(ev);
};
r.readAsText(file);
}
);
} // end fileToString()
}https://stackoverflow.com/questions/46513123
复制相似问题