如何在离线情况下将txt/csv文件加载到JavaScript字符串/数组中

5
我有一个小的html/javascript网页,想要在浏览器离线运行。
同样地,该页面可以包含图像或css文件,并在离线时使用它们,我想要包含一个3MB的电子表格,javascript将其读入2D数组中,希望它能够在IE8以及现代浏览器上运行。
C:\Folder\index.html
C:\Folder\code.js
C:\Folder\picture.png
C:\Folder\spreadsheet.csv

我在网上找到了多种方法,比如

<script src="jquery-csv.js"></script>
var table = $.csv.toArrays("spreadsheet.csv");

或者
d3.text('spreadsheet.csv', function(error, _data){
            var table = d3.csv.parseRows(_data);
        });

或者

$(document).ready(function() {
    $.ajax({
        type: "GET",
        url: "data.txt",
        dataType: "text",
        success: function(data) {processData(data);}
     });
});

但是我经常会遇到同源策略错误,例如:
XMLHttpRequest cannot load file://data.txt. Received an invalid response. Origin 'null' is therefore not allowed access.

Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match. 

我似乎无法使它们离线工作。我该怎么做才能实现呢?
编辑:
我已经成功让以下内容在Firefox上仅对文本文件起作用,使用了在这里找到的CSVToArray函数,对于这样大小的文件来说速度相当缓慢,并使用了一个隐藏的iframe。
最终,最好能够在IE8上运行,如果我使用csv而不是txt文件也是如此,但至少这是一个开始。
<iframe style="display:none;" id='text' src = 'file.txt' onload='read_text_file()'>
</iframe>

<script type="text/javascript" >

function read_text_file() {
    var text = document.getElementById('text').contentDocument.body.firstChild.innerHTML;
    var table = CSVToArray(text); 
}

对于IE8,我设法在小范围内使其正常工作,但对于3MB的文件,它偶尔会导致浏览器崩溃,并且总是会向用户发出大量警告消息,说明正在使用ActiveX,并且会提示脚本会减慢计算机的速度。

    window.onLoad = readFileInIE("file.csv");

    function readFileInIE(filePath) {

        try {
            var fso = new ActiveXObject("Scripting.FileSystemObject");      
            var file = fso.OpenTextFile(filePath, true);                                    
            var text = file.ReadAll();  
            var table = CSVToArray(text);
            file.Close();

            return fileContent;
        } catch (e) {
            if (e.number == -2146827859) {
                alert('Unable to access local files due to browser security settings. ' + 
                    'To overcome this, go to Tools->Internet Options->Security->Custom Level. ' + 
                    'Find the setting for "Initialize and script ActiveX controls not marked as safe" and change it to "Enable" or "Prompt"'); 
            }
        }
    }

不确定,但可能会有html5文件jquery-offline.js有所帮助。 - marathonman
2
这是一个涉及 JavaScript 中本地文件访问的问题。 - Tomas
1
你可以将CSV硬编码在隐藏的<textarea>标签中... - dandavis
HTML5 IndexedDB 可能解决您的问题——您需要将其加载到 IndexedDB 中,然后从那里读取,而不是从文件系统中读取。我正在慢慢地尝试从已被规范删除的 HTML5 文件系统 API 过渡,Firefox 声称使用废弃的(仅在 Chrome 中实现)系统可以完成所有工作,而且 IndexedDB 对象存储是持久性的,需要对其进行更深入的研究。 - Arthur Weborg
5个回答

1
这可能在IE8中不起作用,但HTML5 API对于此非常有用。只需使用:

(这个代码块需要翻译吗?)

window.onload = function() {
    var fileInput = document.getElementById('fileInput');             

    fileInput.addEventListener('change', function(e) {
        var file = fileInput.files[0];
        var textType = //format you'd like to recieve;
        if (file.type.match(textType)) {
            var reader = new FileReader();              
            reader.onload = function(e) {
                // apply magic here
            }
            reader.readAsText(file);
        }
        else
        {
            fileDisplayArea.innerText ="Sorry matey, can't help you with that filetype."
        }
    });    
}

然后,一个简单的 .html 文件看起来像这样就可以解决问题:
<html lang="en">
    <head>        
        <script src="script.js"></script>          
    </head>
    <body>
        <div id="page-wrapper">
            <div> 
                <input type="file" id="fileInput">
            </div>
            <pre id="fileDisplayArea"></pre> //display any output here
        </div>
    </body>
</html>

1
你能解释一下如何使用吗?我应该在哪里包含文件名? - Charles Clayton
我已经手动编辑了答案。你可以自动化处理,但我认为这超出了本问题的范围。 - User

0

正如您所意识到的那样,任何基于 AJAX 的解决方案都会受到本地文件访问安全限制的影响。与其寻找特定于浏览器的解决方法,不如使用避免 AJAX 的JSONP方式。

这将要求您预处理 CSV 数据并以更适合 JS 的格式保存它。但这是一个好主意,因为原生 JS 解析很可能比在 JS 中实现的 CSV 解析器性能更好。

它可能看起来大致像这样:

index.html

    </head>
    <body>
        <div id="page-wrapper">
        <div> 
            <input type="file" id="fileInput">
        </div>
        <pre id="fileDisplayArea"></pre> <!-- display any output here -->

        </div>
        <script src="script.js"></script>
        <script src="data.js"></script>
    </body>
</html>

script.js

function processData(data) {
    // Your logic
    // (will be called once data.js is loaded)
}

data.js

processData([
    ["your", "data"]
]);

0

你想要做什么还不太清楚。

使用jQuery可以修改DOM中发生的事件。通过这样做,你可以在完成更改后潜在地保存源代码。然后,您需要用保存的代码替换当前的源代码以在下次打开页面时使用更改。但是,这将是一个非常费力的过程,并且根据您想要做什么,可能会有许多更好的方法来完成它。

此外,关于Shota的帖子。除非有后台运行的服务器,否则无法使用AJAX。如果您决定在服务器上设置系统,则有许多选项可实现您想要的功能。


0

我的评论变得太长了。

你不能像媒体文件一样包含数据文件。最简单的方法是将csv预处理为js数组,然后像js一样包含csv <script src="mydata.csv.js"></script>

离线是指本地文件而不是公共文件吗?第一个建议是升级您的浏览器。如果它是支持所有主要浏览器的本地文件,那么这并不完全合理。抱歉,我相信您有无法升级的原因。但是升级可以解决ie8中非Ecmascript 5支持的问题。

要避免跨域策略,您必须在本地Web服务器上运行文件。因此,您的HTML页面将位于类似localhost:8080的位置,而您的csv将位于localhost:8080/mydata.csv,这使得HTML具有允许访问csv文件的特权,因为它们现在在同一个域上。 D3、jquerycsv现在应该可以工作了。允许任何HTML文件自由访问文件系统是一个巨大的安全风险。

如果本地服务器不是一个选项。每次加载时都必须使用输入字段选择文件。这授予浏览器访问此文件的权限。

在选择文件之后,如果要在主流浏览器(具有 Ecma5)中读取内容,请查看 MDN 上的 FileReader,并且可以在 这里 找到使用示例。对于 ie8 + 9,有 VBscript 支持来读取文件。您可以像使用 JS 一样使用 VB,使用 <script type="text/vbscript"></script>

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接