如何使用来自外部链接的 SheetJS (Amazon S3) 解析 Excel 文件

Posted

技术标签:

【中文标题】如何使用来自外部链接的 SheetJS (Amazon S3) 解析 Excel 文件【英文标题】:How can I parse an Excel file using SheetJS from an external link (Amazon S3) 【发布时间】:2016-08-03 19:36:53 【问题描述】:

我正在尝试解析一个已有 URL 的 Excel 文件。尝试访问文件以使其可读时,我不断收到不同的错误。现在,这是我的代码:

  const input_file = doc.input_file;
  const extension = input_file.split('.').pop();



  let XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
  let oReq = new XMLHttpRequest();
  oReq.open("GET", input_file, true);
  oReq.responseType = "arraybuffer";

  oReq.onload = function(e) 
    let arraybuffer = oReq.responseText;
    /* convert data to binary string */
    let data = new Uint8Array(arraybuffer);
    let arr = new Array();
    for(let i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
    let bstr = arr.join("");

    /* Call XLSX */
    let workbook = XLSX.read(bstr, type:"binary");

    /* DO SOMETHING WITH workbook HERE */
    let firstSheet = workbook.SheetNames[0];
    let parsed = XLSX.utils.sheet_to_csv(firstSheet);
    console.log(parsed);
  

  oReq.send();

当我尝试读取位于let workbook = XLSX.read(bstr, type:"binary");的文件时,我得到的当前错误是:Error: Unsupported file NaN

我不确定阅读该外部链接的最简单方法。有任何想法吗?如果有帮助,我正在使用 Meteor。

【问题讨论】:

这个错误暗示bstr是NaN,所以可能没有收到任何东西。如果有东西被退回,请与console.log(oReq.responseText) 联系。另外,使用oReq.response 而不是oReq.responseText 作为arraybuffer 类型。 【参考方案1】:

这是一个久经考验的答案。

你的代码有两个问题:

    对于二进制文件,应该是let arraybuffer = oReq.response;,而不是let arraybuffer = oReq.responseText;

    您应该在您的 Amazon S3 实例上启用跨域资源共享。只需关注official tutorial here.

这是一个有效的代码笔:

http://codepen.io/KevinWang15/pen/GZXJKj

你在用 nodeJS 吗?

注意:上面的代码只是使用了网络浏览器的(chrome)XMLHttpRequest,我注意到你正在使用

XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest

你在使用类似 nodejs 的东西吗? (对不起,我对 Meteor 不熟悉)

更具体地说,您使用的是driverdan/node-XMLHttpRequest 吗?

我用它和你的代码进行了试验,它导致了完全相同的错误消息。我认为是因为这个XMLHttpRequest 仍然存在与oReq.responseoReq.responseText 的兼容性问题

如果你使用的是nodeJS,我推荐另一个库:ykzts/node-xmlhttprequest

安装它

npm i w3c-xmlhttprequest

改变你的 XMLHttpRequest
let XMLHttpRequest = require('w3c-xmlhttprequest').XMLHttpRequest;

它立即解决了问题!

【讨论】:

【参考方案2】:

一个更好的主意可能是使用 Meteor 的 HTTP package 来获取文件。文档是here

使用添加包

meteor add http

然后使用:

let result = HTTP.get(input_file,function (error,result)
//process result here
);

result.data 将包含您可以使用 SheetJS 轻松解析的 Excel 文件。

但是,请确保您已在 Amazon S3 上允许跨域,否则您将收到以下表单错误:

“请求的资源上不存在'Access-Control-Allow-Origin'标头。因此不允许访问源'blah blah'。”

【讨论】:

当我尝试这个时,result.data 只是返回 null 试试 console.log(result)。它可能在 result.content 中,具体取决于 S3 的响应。当我尝试这个时,它工作得很好。【参考方案3】:

XMLHttpRequest 受Same Origin Policy 限制,这意味着您只能直接从自己的域访问内容。

但是您可以在服务器上创建一个服务,该服务会为您加载工作表并将其传递回客户端。

Here 是一个简单的教程。

但请注意,加载第三方文件的一般方法可能会导致严重的安全问题。 因此,如果您的工作表 URL 是不变的,您可以考虑仅通过 php 脚本加载此特定链接,而不允许任何其他 URL。

【讨论】:

【参考方案4】:

我最终使用了其中一些答案的组合。我想在这里发布它以防万一它对其他人有所帮助。

我开始使用 Achal 提到的 Meteor HTTP 包。

meteor add http

我还从 Meteor 社区添加了一个额外的包,允许添加响应类型。

meteor add aldeed:http

然后,我使用以下代码转换为二进制并可以继续阅读工作表:

HTTP.get(input_file, responseType: 'arraybuffer', function(error, result) 
  let data = new Uint8Array(result.content);
  let arr = new Array();
  for(let i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
  let bstr = arr.join("");

  let workbook = XLSX.read(bstr, type:"binary");
  var first_sheet_name = workbook.SheetNames[0];
  let sheet = workbook.Sheets[first_sheet_name];
  let parsed = XLSX.utils.sheet_to_json(sheet);
);

【讨论】:

以上是关于如何使用来自外部链接的 SheetJS (Amazon S3) 解析 Excel 文件的主要内容,如果未能解决你的问题,请参考以下文章

检查链接是不是来自外部域

如何从 UIWebView 打开 safari.app 中的外部链接?

tld 中断来自外部链接的 ssl 重定向后缺少尾部斜杠

SheetJS / js-xlsx简介

使用SheetJS读写Excel文件

使用SheetJS读写Excel文件