2012-04-12 13 views
1

私はプロジェクト用にGoogle Web Toolkitを使用しており、ブラウザ内のテキストウィンドウで開くテキストファイルを選択します。ここでは、ほとんどの作業コードは次のとおりです。HTML5とJavascript:ファイルAPIを使用したローカルファイルのオープンと読み取り

private DialogBox createUploadBox() { 
    final DialogBox uploadBox = new DialogBox(); 
    VerticalPanel vpanel = new VerticalPanel(); 
    String title = "Select a .gms file to open:"; 
    final FileUpload upload = new FileUpload(); 
    uploadBox.setText(title); 
    uploadBox.setWidget(vpanel); 
    HorizontalPanel buttons = new HorizontalPanel(); 
    HorizontalPanel errorPane = new HorizontalPanel(); 
    Button openButton = new Button("Open", new ClickHandler() { 
     @Override 
     public void onClick(ClickEvent event) { 
      String filename = upload.getFilename(); 
      int len = filename.length(); 
      if (len < 5) { 
       Window.alert("Please enter a valid filename.\n\tFormat: <filename>.gms"); 
      } else if (!filename.substring(len-4).toLowerCase().equals(".gms")) { 
       Window.alert(filename.substring(len-4) + " is not valid.\n\tOnly files of type .gms are allowed."); 
      } else { 
       Window.alert(getFileText(filename)); 
      } 
     } 
     private native String getFileText(String filename) /*-{ 
      // Check for the various File API support. 
      if (window.File && window.FileReader && window.FileList && window.Blob) { 
       // Great success! All the File APIs are supported. 
       var reader = new FileReader(); 
       var file = File(filename); 
       str = reader.readAsText(file); 
       return str; 
      } else { 
       alert('The File APIs are not fully supported in this browser.'); 
       return; 
      } 
     }-*/; 
    }); 
    Button cancelButton = new Button("Cancel", 
      new ClickHandler() { 
     @Override 
     public void onClick(ClickEvent event) { 
      uploadBox.hide();    
     } 
    }); 
    buttons.add(openButton); 
    buttons.add(cancelButton); 
    vpanel.add(upload); 
    vpanel.add(buttons); 
    vpanel.add(errorPane); 
    uploadBox.setAnimationEnabled(true); 
    uploadBox.setGlassEnabled(true); 
    uploadBox.center(); 
    return uploadBox; 
} 

私は実際に私のプログラムでは、この機能を使用しようとするたびに、私が手:

を(NS_ERROR_DOM_SECURITY_ERR):セキュリティエラーは

私はそれが確信していますケース:ケース:

var file = new File(filename, null); 

免責事項:私はJavascriptプログラマーではありません。私がここで作っている明らかな間違い。私はあなただけnew File(name)書き込みを拡張使用することができます見ることができるよう

+0

re:編集 - ウィンドウ/ $ wndはおそらくgwt固有の唯一のポイントです。それと、InputElementインスタンスを渡す方法。 –

答えて

3

を、あなたはほとんど常に$wndを使用する必要があります。 JSNIの詳細については、https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSNI#writingを参照してください。

FirebugやChromeのInspectorのようなものを使ってdebugger文を追加することもできます。このステートメントは、ブレークポイントをそこに置いたかのように、デバッガのJSコードを停止します.Javascriptでデバッグしたり、一度に1行ずつステップしたりして、何が問題になったのかを正確に確認できます。

最後に、読んでいるファイルがブラウザで許可されていますか? http://dev.w3.org/2006/webapi/FileAPI/#dfn-SecurityErrorから、ブラウザにファイルへのアクセスが許可されていないため、そのエラーが発生している可能性があります。 Stringを渡す代わりに、ユーザーが対話している<input type='file' />を渡し、そこから選択したファイルを取得することができます。


更新(遅延のため申し訳ありませんが、どうやら私が作った以前の更新が捨てられてしまった、それを書き換えるために私を少し取った):元のコードで作られている悪い仮定の

カップル。私の読書のほとんどはhttp://www.html5rocks.com/en/tutorials/file/dndfiles/から、少し実験を加えたものです。

  • あなたはFileReader APIであることを本当のあなただけのパスによってユーザファイルシステムから任意のファイルを読み込むことができ
  • と相まって<input type='file' />フィールドからのパス、そして最後に
  • を得ることができることを、まず、同期。セキュリティ上の理由から

ファイル名を読んだとき、ほとんどのブラウザでは、実際のパスを与えていない - ファイルをロードするには十分ではない - あなたはそれが与えるものを見るために、いくつかのブラウザでupload.getFilename()から取得した文字列を確認してください。 2番目の問題はセキュリティ上の問題です。文字列を使って読み込むファイルを指定するだけでファイルシステムから読み込むことはできません。

これらの最初の2つの理由から、inputに、作業中のファイルを尋ねる必要があります。 FileReader APIをサポートするブラウザでは、入力要素のfilesプロパティを読み取ることでこれにアクセスできます。これを得るための2つの簡単な方法 - NativeElementを使って作業する。jsniのgetEventTarget()、または単にFileUpload.getElement()を使用しています。このfilesプロパティはデフォルトで複数の項目を保持していますので、あなたのような場合は、0番目の要素を読み込んでください。最後のピースのために

private native void loadContents(NativeEvent evt) /*-{ 
    if ($wnd.File && $wnd.FileReader && $wnd.FileList && $wnd.Blob) { 
     // Great success! All the File APIs are supported. 
     var reader = new FileReader(); 
     reader.readAsText(evt.target.files[0]); 
//... 

または

private native void loadContents(Element elt) /*-{ 
    if ($wnd.File && $wnd.FileReader && $wnd.FileList && $wnd.Blob) { 
     // Great success! All the File APIs are supported. 
     var reader = new FileReader(); 
     reader.readAsText(elt.files[0]); 
//... 

FileReader APIは非同期です - あなたはすぐに、ファイルの完全な内容を取得しますが、onloadendコールバックが呼び出されるまで待つ必要はありません(やはりhttp://www.html5rocks.com/en/tutorials/file/dndfiles/から)。これらのファイルは、読み込み中にアプリがブロックされたくないほど大きくなる可能性があるため、仕様ではこれがデフォルトとみなされているようです。

私は新しいvoid loadContentsメソッドを作ることになった理由は、代わりにあなたのonClick方法でコードを保つための、ある - これはいくつかを書くことができてもフィールドのChangeEventは、ファイルの読み込みを開始し、消灯したときに、このメソッドが呼び出されます他の方法。

// fields to hold current state 
private String fileName; 
private String contents; 
public void setContents(String contents) { 
    this.contents = contents; 
} 

// helper method to read contents asynchronously 
private native void loadContents(NativeEvent evt) /*-{; 
    if ($wnd.File && $wnd.FileReader && $wnd.FileList && $wnd.Blob) { 
     var that = this; 
     // Great success! All the File APIs are supported. 
     var reader = new FileReader(); 
     reader.readAsText(evt.target.files[0]); 
     reader.onloadend = function(event) { 
      [email protected]::setContents(Ljava/lang/String;)(event.target.result); 
     }; 
    } else { 
     $wnd.alert('The File APIs are not fully supported in this browser.'); 
    } 
}-*/; 

// original createUploadBox 
private DialogBox createUploadBox() { 
    final DialogBox uploadBox = new DialogBox(); 
    VerticalPanel vpanel = new VerticalPanel(); 
    String title = "Select a .gms file to open:"; 
    final FileUpload upload = new FileUpload(); 
    upload.addChangeHandler(new ChangeHandler() { 
    @Override 
    public void onChange(ChangeEvent event) { 
     loadContents(event.getNativeEvent()); 
     fileName = upload.getFilename(); 
    } 
    }); 
    // continue setup 

[OK]ボタンは、フィールドから読み取ります。おそらくClickHandlerのコンテンツがnullでないことを確認し、FileUploadChangeEventがオフになったときにそれをヌルにすることも賢明でしょう。

+0

申し訳ありませんが、前にも述べたように、私はJavaScriptのプログラマーではありません。そのビットを使用する具体的な例を教えてください。 – holocron

+0

私は、あなたがブラウザにファイルへのアクセスを許可していないとあなたは正しいと思います。フォームでファイルを提出する必要がありますか? – holocron

+1

提出しませんが、ユーザーがファイルを参照できるようにしてから、選択内容を確認してください。 http://www.html5rocks.com/en/tutorials/file/dndfiles/#toc-reading-filesを参照してください。ChangeEventのハンドラをFileUploadウィジェットに追加します。ユーザーは参照をクリックして何かを選択します。 handleFileSelectのようにNativeEventを読み取ることができます。 FileUpload以外のカスタムウィジェットが必要な場合があります。これは私がこれを使ってからしばらくしています。 Qをほぼ実用的なコードサンプルで更新すると、さらにフォローアップできるかどうかがわかります。 –

関連する問題