1

プロジェクトに Google Web Toolkit を使用しており、ブラウザ内のテキスト ウィンドウで開くテキスト ファイルをユーザーに選択してもらいたいと考えています。これがほとんど機能するコードです:

 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 プログラマーではありません。ここで明らかに間違いを犯している場合は、遠慮なく指摘してください。

4

2 に答える 2

3

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

debuggerFirebug や Chrome の Inspector などを使用しているときにステートメントを追加することも価値があります。このステートメントは、デバッガーにブレークポイントを置いたかのように、デバッガーで JS コードを停止し、Javascript でデバッグできるようにします。

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


更新(遅れて申し訳ありません。以前に行った更新が破棄されたようで、書き直すのに少し時間がかかりました):

元のコードで行われているいくつかの悪い仮定。私の読書のほとんどはhttp://www.html5rocks.com/en/tutorials/file/dndfiles/からのもので、さらに少し実験しています。

  • <input type='file' />まず、フィールドから実際のパスを取得できることと、
  • パスだけでユーザーファイルシステムから任意のファイルを読み取ることができ、最後に
  • FileReaderAPI が同期的であること。

セキュリティ上の理由から、ほとんどのブラウザはファイル名を読み取ったときに実際のパスを提供しませんupload.getFilename().いくつかのブラウザで取得した文字列をチェックして、ファイルをロードするのに十分ではありません. 2 番目の問題は、セキュリティの問題でもあります。文字列を使用して読み取るファイルを指定するだけで、ファイル システムからの読み取りを許可しても、ほとんどメリットはありません。

inputこれらの最初の 2 つの理由から、作業中のファイルについてに問い合わせる必要があります。FileReader API をサポートするブラウザーfilesは、input 要素のプロパティを読み取ることでこれにアクセスできます。これを取得する 2 つの簡単な方法 - jsni で NativeElement.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]);
//...

最後の部分では、FileReaderAPI は非同期です。ファイルの完全なコンテンツをすぐに取得することはできませんが、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) {
            that.@com.sencha.gxt.examples.test.client.Test::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

于 2012-04-12T22:22:22.583 に答える
0

私が見る限り、new File(name)拡張機能を作成する場合にのみ使用できます: https://developer.mozilla.org/en/Extensions/Using_the_DOM_File_API_in_chrome_code

于 2012-04-12T22:20:37.030 に答える