31

バックグラウンド:

JavaScript/HTMLのみを使用し、ファイルシステムから直接ブラウザーで開くことができる「アプリ」を作成したいと考えています。このアプリは、別のファイルからデータを読み取れる必要があります。次に、JS を使用してそれを解析し、ページをレンダリングします。簡単な例として、CSV ファイル(ここからダウンロード)があるとします。

Mark Rodgers,mark.rodgers@company.com,Accounting
[...]
Melissa Jones,melissa@company.com,CEO

JS を使用してファイルを読み取り、その中のデータを使用してページを生成できるようにしたいと考えています。

これまでに達成したこと:

デモ(右クリック -> [名前を付けて保存] で HTML をコンピューターに保存します)。また、 jsfiddleでも半壊れた方法で利用できます (レイアウトは壊れていますが、機能的には正しいはずです)。

CSV テキスト ファイルをドラッグ アンド ドロップ ボックスにドラッグ アンド ドロップするか、ファイル メニューを使用してテキスト ファイルを選択するだけで、JavaScript がファイルを読み取って解析し、テーブルに入力します。

これは FileReader API に依存しています。面倒な作業のほとんどは、この関数によって行われます。

function handleFileSelect(evt) {
    evt.stopPropagation();
    evt.preventDefault();

    var files = evt.target.files || evt.dataTransfer.files; // FileList object.
    var file = files[0];

    // this creates the FileReader and reads stuff as text
    var fr = new FileReader();
    fr.onload = parse;
    fr.readAsText(file);

    // this is the function that actually parses the file
    // and populates the table
    function parse()
    {
        var table = document.getElementById('emps');
        var employees = fr.result.split('\n'); var c = 0;
        for (var i in employees)
        {
            var employee = employees[i].split(',');
            if (employee.length == 3)
            {
                var row = document.createElement('tr');
                row.innerHTML = "<td>" + employee.join("</td><td>") + "</td>";
                table.appendChild(row);
                c++;
            }
        }
        document.getElementById('result').innerHTML = '<span>Added ' + c + ' employees from file: ' + file.name + '</span>';
    }
}

これはほとんど問題ありませんが、ユーザーが手動でファイルをロードするのは不便です。理想的には、自動的にロードできるはずですが、セキュリティ上の理由から、それを許可するブラウザーはありません... まだ.

ソリューション要件:

  • オフラインで作業する必要があります。つまり、どのオンライン サービスにも依存できません。これには、ローカル マシンで実行されている HTTP サーバーも含まれます。アイデアは、ブラウザがインストールされているだけの任意のコンピューターでこれを実行することです。

  • プロトコルを使用してページを開いたときに機能する必要がありfile:///ます (つまり、ハード ドライブ上の HTML ページ)。

  • サード パーティのアドオン (例: Flash、Java、震える ActiveX) に依存しないでくださいページがfile:///

  • 任意のデータを受け入れることができなければなりません。これにより、JSON のようにすぐに使用できる適切な形式でファイルをロードすることが除外されます。

  • Firefox または Chrome のいずれか (理想的には両方) で動作する場合は問題ありません。実験的な API に依存することもできます

ファイル名は事前にわかっているので、HTML 自体にコーディングできます。ディスクからファイルを読み取ることができるソリューションであれば問題ありません。FileReader API を使用する必要はありません

したがって、ファイルをページにロードするための巧妙なハックがあれば、それも問題ありません (目に見えない iframe にロードして、JS にコンテンツを取得させることができます)。それもOKです。

4

6 に答える 6

4

ローカルまたはサーバー上で動作する外部ファイルで JSON データを使用する例を次に示します。この例では、ブラウザーの言語設定を使用して、ローカライズされた html を含む < script > をロードし、その json オブジェクトを処理して、指定されたタグ内のデータをローカライズされたコンテンツでリセットします。

<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head>
<script>
    function setLang(){
        for (var i=0;i<items.length;i++){
            term=document.getElementById(items[i].id)
            if (term) term.innerHTML=items[i].value
        }
    }
    var lang=navigator.userLanguage || navigator.language;
    var script=document.createElement("script");
    script.src=document.URL+"-"+lang.substring(0,2)+".js"
    var head = document.getElementsByTagName('head')[0]
    head.insertBefore(script,head.firstChild)
</script>
</head>
<body onload='setLang()'>
<div id="string1" class="txt">This is the default text of string1.</div> 
<div id="string2" class="txt">This is the default text of string2.</div>
</body></html>

このためのデータ ファイルは次のようになります。

items=[
{"id":"string1","value":"Localized text of string1."},
{"id":"string2", "value":"Localized text of string2."}
];

ただし、任意のパラメーターを使用して適切なファイルを条件付きで読み込むことができ (< head > の最初のタグとして挿入されるため、どこでも使用できます)、JSON 形式は多種多様なデータを処理できます。関数 setLang の名前をより適切なものに変更し、必要に応じて変更することをお勧めします。たとえば、行を追加し、データを含むフィールドを追加します (その部分には既にハンドルがあるようです)。 JSON は次のようになります。

items=[
{"fname":"john","lname":"smith","address":"1 1st St","phone":"555-1212"},
{"fname":"jane","lname":"smith","address":"1 1st St","phone":"555-1212"}
];

データを前処理する必要がある場合、awk は非常に便利です。次のようになります: (untested guestimate)

awk 'BEGIN{FS=",";print "items=[\n"}
{printf "{\"fname\":\"%s\",\"lname\":\"smith\",\"address\":\"1 1st St\",\"phone\":\"555-1212\"},\n", $1, $2, $3, $4}
END{print "];"}' file.csv > file.js

編集: OP がより明確になったので、mozilla ブラウザーのみが file:// の XMLHttpRequest をすぐに許可し、chrome (おそらく他の webkit ベースのブラウザー)を許可するように構成できます。IE<10 では動作しない可能性があることを知っていれば、次のことができます。

var filePath = "your_file.txt";
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET",filePath,false);
xmlhttp.overrideMimeType('text/plain');
xmlhttp.send(null);
//maybe check status !=404 here
var fileContent = xmlhttp.responseText;
var fileArray = fileContent.split('\n')
var n = fileArray.length;
//process your data from here probably using split again for ','

同様の問題を抱えている可能性があるが、データ形式をある程度制御できる他の人のために、初期の json-p バリエーションを残しています。これは、すべての JavaScript 対応ブラウザで動作するためです。ただし、(小さな Web サーバーを実行する以外に) IE で動作させる方法を誰かが知っている場合は、編集してください。

編集2:

mozilla ブラウザでは、iframe も使用できます

<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head>
<script>
function showContents(frameObject){
    alert(frameObject.contentDocument.body.innerHTML);
    //replace with your code
}
</script>
</head>
<body onload='showContents()'>
<iframe id="frametest" src="data.txt" onload="showContents(this);" 
    style="visibility:hidden;display:none"></iframe>
</body></html>
于 2012-11-27T04:51:48.610 に答える
4

これは私がFirefoxに使用したコードで、移植性はありませんが、作品:

OPがコメントしたように、enablePrivilege()非推奨になったため、これは使用可能と見なされます。prefs.jsしかし、以前のプロファイルを使用している私の Firefox は引き続き私のコードで動作するため、 (これらの設定を非表示にしているため) 少し掘り下げabout:configます。動作させるために必要な設定は次のとおりです。

user_pref("capability.principal.codebase.p0.granted", "UniversalXPConnect");
user_pref("capability.principal.codebase.p0.id", "file://");  // path to the html file.
user_pref("capability.principal.codebase.p0.subjectName", "");

コードは次のとおりです。

var File = function(file) {
  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
  var ios = Components.classes["@mozilla.org/network/io-service;1"]
                            .getService(Components.interfaces.nsIIOService);
  if (!File.baseURI) {
    File.baseURI = ios.newURI(location.href.substring(0, location.href.lastIndexOf('/')+1), null, null);
    File.baseFolder = File.baseURI.QueryInterface(Components.interfaces.nsIFileURL).file.path;
  }
  var URL = ios.newURI(file, null, File.baseURI);
  this.fptr = URL.QueryInterface(Components.interfaces.nsIFileURL).file;
}

File.prototype = {
  write: function(data) {
    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
    var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                             .createInstance(Components.interfaces.nsIFileOutputStream);
    foStream.init(this.fptr, 0x02 | 0x08 | 0x20, 0666, 0);
    var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
                              .createInstance(Components.interfaces.nsIConverterOutputStream);
    converter.init(foStream, null, 0, 0);
    converter.writeString(data);
    converter.close();
  },
  read: function() {
    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
    var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
                            .createInstance(Components.interfaces.nsIFileInputStream);
    var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
                            .createInstance(Components.interfaces.nsIConverterInputStream);
    fstream.init(this.fptr, -1, 0, 0);
    cstream.init(fstream, null, 0, 0);
    var data = "";
    // let (str = {}) { // use this only when using javascript 1.8
    var str = {};
      cstream.readString(0xffffffff, str);
      data = str.value;
    // }
    cstream.close();
    return data;
  }
};
于 2012-11-17T07:16:58.153 に答える
3

csvファイルがアプリと同じディレクトリにあると仮定すると、AJAXを使用してファイルをロードします。私の知る限り、ファイルをテキスト形式で取得してから解析することができます。これはIEとFirefoxで機能するはずですが、Chromeでは機能しません(--allow-file-access-from-filesコマンドライン設定でchromeを実行している場合を除く)。

于 2012-12-03T09:10:12.810 に答える
2

これは、javascript XMLHttpRequest() クラスを使用して非常に簡単に実行できます。

function FileHelper()
{}
{
    FileHelper.readStringFromFileAtPath = function(pathOfFileToReadFrom)
    {
        var request = new XMLHttpRequest();
        request.open("GET", pathOfFileToReadFrom, false);
        request.send(null);
        var returnValue = request.responseText;

        return returnValue;
    }
}

...

var text = FileHelper.readStringFromFileAtPath ( "mytext.txt" );
于 2014-03-03T16:22:02.850 に答える
1

私が理解しているように、ファイルの内容は完全にあなたの管理下にあり、特定の形式である必要はありませんか? そして、あなたは読む方法だけが必要ですか?

グローバル関数「handleFile」を宣言できます。外部ファイルでは、コンテンツは次のようにする必要があります。

handleFile('Mark Rodgers,mark.rodgers@company.com,Accounting');

ファイルを「読み取る」には、対応する src 属性を持つ script 要素を追加するだけです。関数「handleFile」で、コンテンツを取得します。

ファイルの場所はおそらく最初にユーザーが設定する必要がありますが、その後、その場所を localStorage などに保存できます。

于 2012-11-26T14:15:12.157 に答える
1

ファイルが同じディレクトリまたはサブディレクトリにあることを確認し、AJAX を使用してファイルをロードします。

スクリプト タグとは異なり、コンテンツにアクセスできます。

于 2012-11-27T06:51:56.297 に答える