[英]Reading a local file a _second_ time using the html5 file reader API
[英]HTML5 and Javascript : Opening and Reading a Local File with File API
我正在使用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程序員,請隨時指出我在這里犯的任何明顯錯誤。
你應該幾乎總是使用$wnd
而不是使用window
。 有關JSNI的更多詳細信息,請參閱https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsJSNI#writing 。
在使用Firebug或Chrome的Inspector之類的東西時添加debugger
語句也是值得的。 這個語句會停止調試器中的JS代碼,好像你在那里放了一個斷點,允許你在Javascript中調試,一次踩一行來查看到底出了什么問題。
最后,您確定瀏覽器允許您正在閱讀的文件嗎? 從http://dev.w3.org/2006/webapi/FileAPI/#dfn-SecurityError ,可能發生該錯誤,因為瀏覽器未被允許訪問該文件。 您可以傳入用戶正在與之交互的<input type='file' />
,而不是傳入String,並從中獲取他們選擇的文件。
更新(抱歉延遲,顯然我所做的早期更新被扔掉了,我帶了一點重寫它):
幾個壞假設正在原始代碼中。 我的大部分閱讀來自http://www.html5rocks.com/en/tutorials/file/dndfiles/ ,還有一些實驗。
<input type='file' />
字段獲得一個真實的路徑,再加上 FileReader
API是同步的。 出於安全原因,大多數瀏覽器在讀取文件名時都沒有提供真實的路徑 - 在幾個瀏覽器中檢查從upload.getFilename()
獲得的字符串,看看它給出了什么 - 不足以加載文件。 第二個問題也是一個安全問題 - 只需使用字符串來指定要讀取的文件就可以從文件系統中讀取,這樣做很少。
出於前兩個原因,您需要詢問input
它正在處理的文件。 支持FileReader API的瀏覽器允許通過讀取input元素的files
屬性來訪問它。 有兩種簡單的方法 - 在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]);
//...
對於最后一篇文章, 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) {
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
檢查內容是非空的可能是明智的,甚至可能在FileUpload
的ChangeEvent
關閉時將其ClickHandler
。
據我所知,在編寫擴展時只能使用new File(name)
: https : //developer.mozilla.org/en/Extensions/Using_the_DOM_File_API_in_chrome_code
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.