在各种浏览器中使用javascript在客户端读取文件内容


112

我试图提供一种仅脚本解决方案,用于通过浏览器读取客户端计算机上文件的内容。

我有一个可与Firefox和Internet Explorer一起使用的解决方案。它不是很漂亮,但是我现在只是在尝试:

function getFileContents() {
    var fileForUpload = document.forms[0].fileForUpload;
    var fileName = fileForUpload.value;

    if (fileForUpload.files) {
        var fileContents = fileForUpload.files.item(0).getAsBinary();
        document.forms[0].fileContents.innerHTML = fileContents;
    } else {
        // try the IE method
        var fileContents = ieReadFile(fileName);
        document.forms[0].fileContents.innerHTML = fileContents;
    }
}       

function ieReadFile(filename) 
{
    try
    {
        var fso  = new ActiveXObject("Scripting.FileSystemObject"); 
        var fh = fso.OpenTextFile(filename, 1); 
        var contents = fh.ReadAll(); 
        fh.Close();
        return contents;
    }
    catch (Exception)
    {
        return "Cannot open file :(";
    }
}

我可以打电话getFileContents(),它将内容写入fileContents文本区域。

有其他浏览器可以做到这一点吗?

目前,我最关心的是Safari和Chrome浏览器,但是我愿意接受任何其他浏览器的建议。

编辑:回答问题,“为什么要这样做?”:

基本上,我想在客户端对文件内容和一次性密码进行哈希处理,这样我就可以将此信息发回作为验证。


不是我有一个答案,而是为了清楚起见,您是否需要知道文件的位置?如果不是,是否必须从文件输入中读取文件的位置,或者可以是文本框/文本区域/其他内容?
Darko Z

好问题。不,我不太在乎文件的来源,仅在乎其内容。使用文件输入对我来说似乎是明智的,因为它是本机html-我要做的事少了一点。
Damovisa

您为什么要这么做?服务器就是这样做的。
geowa4

好的,简而言之:用户输入密码并选择一个文件。密码将与文件内容进行哈希运算,并与文件一起发送到服务器。当它到达那里时,我可以验证是否使用了正确的客户端密码。
Damovisa

Answers:


157

编辑以添加有关File API的信息

自从我最初写这个答案以来,文件API就已经被提议作为标准并在大多数浏览器中实现(从IE 10开始,它增加了FileReader对此处描述的API的支持,尽管还不是FileAPI)。该API比旧的Mozilla API稍微复杂一点,因为它旨在支持文件的异步读取,对二进制文件的更好支持以及对不同文本编码的解码。Mozilla开发人员网络上一些可用的文档,以及各种在线示例。您将按以下方式使用它:

var file = document.getElementById("fileForUpload").files[0];
if (file) {
    var reader = new FileReader();
    reader.readAsText(file, "UTF-8");
    reader.onload = function (evt) {
        document.getElementById("fileContents").innerHTML = evt.target.result;
    }
    reader.onerror = function (evt) {
        document.getElementById("fileContents").innerHTML = "error reading file";
    }
}

原始答案

在WebKit中似乎没有办法做到这一点(因此,Safari和Chrome)。File对象具有的唯一键是fileNamefileSize。根据支持File和FileList 的提交消息,这些是受Mozilla的File对象启发的,但它们似乎仅支持部分功能。

如果您想更改此设置,则始终可以将补丁发送到WebKit项目。另一种可能性是建议将Mozilla API包含在HTML 5中。在WHATWG的邮件列表是可能做到这一点的最好的地方。如果这样做,那么至少在几年后,很有可能会有跨浏览器的方式来做到这一点。当然,提交修补程序或提议以将其包含到HTML 5中确实意味着捍卫该想法的一些工作,但是Firefox已经实现了它的事实为您提供了一些起点。


谢谢您-我认为我目前没有足够的精力来提交补丁。无论如何,在您不了解的情况下,您可能不希望发生这种事情。这有点破坏了浏览器沙箱……
Damovisa

4
它不会破坏浏览器沙箱,因为您有意选择上传该文件。如果它可以到达服务器,则可以返回浏览器,而只需要进行一次额外的往返。考虑到使离线模式适用于Web应用程序的工作,这将是一个合理的功能。
布赖恩·坎贝尔

嗯,实际上这是一个公平的观点。用户可以选择该文件。谢谢。
Damovisa

@Damovisa我不知道您是否仍然在乎,但我想我会更新答案,以提及新的File API,该API可以满足您的需求,并在Firefox,Chrome和每苹果浏览器。
布莱恩·坎贝尔

太好了,谢谢你。我已经转移到其他工作了,但是很高兴知道答案在这里:)
Damovisa 2011年

24

为了读取用户选择的文件,可以使用文件打开对话框使用<input type="file">标签。您可以从MSDN中找到有关它的信息。选择文件后,可以使用FileReader API读取内容。

function onFileLoad(elementId, event) {
    document.getElementById(elementId).innerText = event.target.result;
}

function onChooseFile(event, onLoadFileHandler) {
    if (typeof window.FileReader !== 'function')
        throw ("The file API isn't supported on this browser.");
    let input = event.target;
    if (!input)
        throw ("The browser does not properly implement the event object");
    if (!input.files)
        throw ("This browser does not support the `files` property of the file input.");
    if (!input.files[0])
        return undefined;
    let file = input.files[0];
    let fr = new FileReader();
    fr.onload = onLoadFileHandler;
    fr.readAsText(file);
}
<input type='file' onchange='onChooseFile(event, onFileLoad.bind(this, "contents"))' />
<p id="contents"></p>


在Internet Explorer中无法使用。
Merwais Muafaq

4

编码愉快!
如果您在Internet Explorer上收到错误消息,请更改安全设置以允许ActiveX

var CallBackFunction = function(content)
{
    alert(content);
}
ReadFileAllBrowsers(document.getElementById("file_upload"), CallBackFunction); 

//Tested in Mozilla Firefox browser, Chrome
function ReadFileAllBrowsers(FileElement, CallBackFunction)
{
try
{
    var file = FileElement.files[0];
    var contents_ = "";

     if (file) {
        var reader = new FileReader();
        reader.readAsText(file, "UTF-8");
        reader.onload = function(evt)
        {
            CallBackFunction(evt.target.result);
        }
        reader.onerror = function (evt) {
            alert("Error reading file");
        }
    }
}
catch (Exception)
 {
    var fall_back =  ieReadFile(FileElement.value);
    if(fall_back != false)
    {
        CallBackFunction(fall_back);
    }
 }
}

///Reading files with Internet Explorer
function ieReadFile(filename)
{
 try
 {
    var fso  = new ActiveXObject("Scripting.FileSystemObject");
    var fh = fso.OpenTextFile(filename, 1);
    var contents = fh.ReadAll();
    fh.Close();
    return contents;
 }
 catch (Exception)
  {
    alert(Exception);
    return false;
  }
 }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.