HTML5和Javascript:打开和读取使用文件API本地文件(HTML5 and [remov

2019-07-28 23:02发布

我使用谷歌Web工具包的一个项目,并希望用户选择一个文本文件,在浏览器内置的文本窗口中打开。 这里的几乎工作的代码:

 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程序员任何延伸,请随时指出任何明显的失误,我在这儿举行。

Answer 1:

而不是使用的window ,你应该总是使用$wnd 。 见https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSNI#writing有关JSNI更多细节。

它也可能是值得添加debugger ,而使用像萤火虫,或Chrome的督察声明。 该声明将在调试器停止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' />场,加上
  • 你可以仅仅通过读取路径从用户的文件系统中任意文件,最后
  • FileReader API是同步的。

出于安全原因,当你阅读的文件名,大多数浏览器不给现实路径-检查你得到字符串upload.getFilename()在多个浏览器,看看它给-没有足够的加载文件。 第二个问题也是一个安全的事情 - 却寥寥无几可以来只允许使用一个字符串指定读取文件从文件系统读取。

对于前两个原因,而不是你需要询问input它正在工作的文件。 支持的FileReader API浏览器允许通过读取访问这个files的输入元素的属性。 两种简单的方法来得到这个 - 在JSNI与NativeElement.getEventTarget()工作,或只是FileUpload.getElement工作()。 请记住,这个files属性保存默认多个项目,所以像你这样的情况下,刚读了零个元素。

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 /教程/文件/ 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

然后“确定”按钮,从地里读取。 或许,这将是明智的检查内容是在非空ClickHandler ,甚至空出来,当FileUploadChangeEvent熄灭。



Answer 2:

至于我能看到你只能用new File(name)编写扩展时: https://developer.mozilla.org/en/Extensions/Using_the_DOM_File_API_in_chrome_code



文章来源: HTML5 and Javascript : Opening and Reading a Local File with File API