【问题标题】:XMLHTTPRequest.response is null when trying to read an excel file尝试读取 excel 文件时 XMLHTTPRequest.response 为空
【发布时间】:2016-11-04 04:40:42
【问题描述】:

您好,我正在尝试使用下面的打字稿来抓取一个 excel 文件,然后将其转换为 json 以用作我正在使用的图表的数据源。它在 onload 函数中出现问题,因为我认为 .response = null - readystate = 1 (OPENED) 和 status = 0 (Open or Unsent)。不太确定它是空的。我读过 readstate 需要 = 4 和 status = 200 (完成打开它)才能工作。但我不知道我该怎么做?

import { Injectable } from '@angular/core';
import { read, IWorkBook, IWorkSheet, utils } from 'ts-xlsx';

@Injectable()
export class OperationDataService {
    oUrl: string;
    xhr: any;
    wb: IWorkBook;
    wbSheet: IWorkSheet;
    arraybuffer: any;
    data: any;
    arr: any;
    bstr: any;

    getData() {
        this.oUrl = './assets/operations.xlsx';
        this.xhr = new XMLHttpRequest();
        this.xhr.open('GET', this.oUrl, true);
        this.xhr.responseType = 'arraybuffer';

        console.log('Service Constructor ' + this.xhr.open + ' - ' + this.xhr.readyState + ' - ' + this.xhr.response + ' - ' + this.xhr.status);

        if (this.xhr.readyState === 4) {

            if (this.xhr.status === 200) {

                this.xhr.onload = function (e) {
                    console.log('in side function');

                    this.arraybuffer = this.xhr.response;

                    console.log('ArrayBuffer ' + this.arraybuffer);

                    /* convert data to binary string */
                    this.data = new Uint8Array(this.arraybuffer);
                    this.arr = new Array();

                    for (let item of this.data) {
                        this.arr[item] = String.fromCharCode(this.data[item]);
                    }

                    this.bstr = this.arr.join('');
                    console.log(this.xhr.responseText);

                    this.wb = read(this.bstr, { type: 'binary' });
                    this.wbSheet = this.wb.Sheets[0];

                    this.objAr = utils.sheet_to_json(this.wbSheet, { header: 1 });
                    console.log(utils.sheet_to_json(this.wbSheet, { header: 1 }));
                    console.log('get data set');

                    return this.objAr;
                };
            }
        }

        this.xhr.send();
    }

}

更新

感谢下面让我使用 javescript lib 将 excel 转换为 json - 似乎是 ts-xlsx 依赖项中的 JSzip 版本的问题,但 XMLHtpRequest GET 已经工作我可以显示二进制数据浏览器。

import { Injectable } from '@angular/core';
import { read, IWorkBook, IWorkSheet, utils } from 'ts-xlsx';

@Injectable()
export class OperationDataService {
    oUrl: string;
    xhr: any;
    wb: IWorkBook;
    wbSheet: IWorkSheet;
    arraybuffer: any;
    data: any;
    arr: any;
    bstr: any;

    getData() {
        this.oUrl = './assets/operations.xlsx';
        this.xhr = new XMLHttpRequest();
        this.xhr.open('GET', this.oUrl, true);
        this.xhr.responseType = 'arraybuffer';

        this.xhr.addEventListener('load', function() {

                    this.arraybuffer = this.xhr.response;

                    // /* convert data to binary string */
                    this.data = new Uint8Array(this.arraybuffer);
                    this.arr = new Array();

                    for (let i = 0; i !== this.data.length; ++i) {
                    this.arr[i] = String.fromCharCode(this.data[i]);
                    }
                    this.bstr = this.arr.join('');

                    this.wb = read(this.bstr, { type: 'binary' });

                    this.wbSheet = this.wb.Sheets[0];
                    this.objAr = utils.sheet_to_json(this.wbSheet, { header: 1 });

                    return this.objAr;

            }.bind(this));

            this.xhr.send(null);
        }

    }

【问题讨论】:

    标签: javascript angular typescript xmlhttprequest


    【解决方案1】:

    使用XMLHttpRequest can be simpler 加载文件比那个:

    this.oUrl = './assets/operations.xlsx';
    this.xhr = new XMLHttpRequest();
    this.xhr.addEventListener("load", function() {
        var arraybuffer = this.response;
        ...
    });
    this.xhr.open('GET', this.oUrl, true);
    this.xhr.responseType = 'arraybuffer';
    

    你也可以按照自己的方式做,但是应该是这样的:

    this.xhr.onreadystatechange =() => {
        if (this.xhr.readyState === 4 && this.xhr.status === 200) {
            this.arraybuffer = this.xhr.response;
    
        }
    }
    

    如果您使用的是onload 事件,则无需检查readyState
    无论如何,您从未真正添加过事件侦听器,因为只有在 readyState === 4status === 200 才添加它,这在您实际发送请求之前永远不会发生。

    至于响应,看起来像这样,因为xlsx 文件被压缩了。


    编辑

    如果您将事件侦听器函数指定为匿名函数,那么该函数主体中的 this 将不是您的对象,而是 XMLHttpRequest 对象,因此它应该是:

    this.xhr.addEventListener("load", function() {
        var arraybuffer = this.response;
        ...
    });
    

    除非你绑定它:

    this.xhr.addEventListener("load", function() {
        var arraybuffer = this.xhr.response;
        ...
    }.bind(this));
    

    如果您使用箭头函数,那么 this 将是您的对象:

    this.xhr.addEventListener("load",() => {
        var arraybuffer = this.xhr.response;
        ...
    });
    

    【讨论】:

    • 感谢我尝试使用第一个代码示例 - 只是为了看看它是否有效,我在浏览器中遇到同样的错误 - Cannot read property 'response' of undefined.
    • getData() { this.oUrl = './assets/operations.xlsx'; this.xhr = new XMLHttpRequest(); this.xhr.addEventListener('load', function () { this.arraybuffer = this.xhr.response; }); this.xhr.open('GET', this.oUrl, true); this.xhr.responseType = 'arraybuffer'; this.xhr.send(); }
    • 你没有提到你的问题中的任何错误。无论如何,请检查我修改后的答案。
    猜你喜欢
    • 2020-02-07
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多