Đọc nội dung tệp ở phía máy khách bằng javascript trong các trình duyệt khác nhau


113

Tôi đang cố gắng cung cấp giải pháp chỉ dành cho tập lệnh để đọc nội dung của tệp trên máy khách thông qua trình duyệt.

Tôi có một giải pháp hoạt động với Firefox và Internet Explorer. Nó không đẹp, nhưng tôi chỉ đang thử những thứ vào lúc này:

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 :(";
    }
}

Tôi có thể gọi getFileContents()và nó sẽ ghi nội dung vào vùng fileContentsvăn bản.

Có cách nào để làm điều này trong các trình duyệt khác không?

Tôi quan tâm nhất đến Safari và Chrome vào lúc này, nhưng tôi sẵn sàng đón nhận các đề xuất cho bất kỳ trình duyệt nào khác.

Chỉnh sửa: Để trả lời cho câu hỏi, "Tại sao bạn muốn làm điều này?":

Về cơ bản, tôi muốn băm nội dung tệp cùng với mật khẩu dùng một lần ở phía máy khách để tôi có thể gửi lại thông tin này dưới dạng xác minh.


không phải tôi có câu trả lời mà chỉ vì mục đích rõ ràng, bạn có cần biết vị trí của tệp không? Nếu không, vị trí của tệp có phải được đọc từ đầu vào tệp hay nó có thể là hộp văn bản / textarea / bất cứ điều gì không?
Darko Z

Câu hỏi hay. Không, tôi không thực sự quan tâm đến nguồn gốc của tệp, chỉ quan tâm đến nội dung của nó. Sử dụng đầu vào tệp có vẻ hợp lý đối với tôi mặc dù đó là html gốc - tôi phải làm một việc ít hơn.
Damovisa

tại sao bạn lại muốn làm điều này? máy chủ được sử dụng để làm điều đó.
geowa4

Ok, nói ngắn gọn: Người dùng nhập mật khẩu và chọn một tệp. Mật khẩu được băm cùng với nội dung tệp và mật khẩu này sẽ được gửi đến máy chủ cùng với tệp. Khi nó đến đó, tôi có thể xác minh rằng mật khẩu máy khách chính xác đã được sử dụng.
Damovisa

Câu trả lời:


159

Đã chỉnh sửa để thêm thông tin về API tệp

Kể từ khi tôi viết câu trả lời này ban đầu, API tệp đã được đề xuất như một tiêu chuẩn và được triển khai trong hầu hết các trình duyệt (kể từ IE 10, hỗ trợ thêm cho FileReaderAPI được mô tả ở đây, mặc dù chưa phải là FileAPI). API phức tạp hơn một chút so với Mozilla API cũ hơn, vì nó được thiết kế để hỗ trợ đọc tệp không đồng bộ, hỗ trợ tốt hơn cho tệp nhị phân và giải mã các mã hóa văn bản khác nhau. Có một số tài liệu có sẵn trên Mạng nhà phát triển Mozilla cũng như các ví dụ khác nhau trực tuyến. Bạn sẽ sử dụng nó như sau:

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";
    }
}

Câu trả lời ban đầu

Dường như không có cách nào để thực hiện việc này trong WebKit (do đó, Safari và Chrome). Các khóa duy nhất mà đối tượng Tệp có là fileNamefileSize. Theo thông báo cam kết hỗ trợ File và FileList, chúng được lấy cảm hứng từ đối tượng File của Mozilla , nhưng chúng dường như chỉ hỗ trợ một tập hợp con các tính năng.

Nếu bạn muốn thay đổi điều này, bạn luôn có thể gửi một bản vá cho dự án WebKit. Một khả năng khác là đề xuất API Mozilla để đưa vào HTML 5 ; các WHATWG mailing list có lẽ là nơi tốt nhất để làm điều đó. Nếu bạn làm điều đó, thì có nhiều khả năng sẽ có một cách trình duyệt chéo để thực hiện điều này, ít nhất là trong một vài năm. Tất nhiên, việc gửi một bản vá hoặc một đề xuất để đưa vào HTML 5 có nghĩa là một số công việc bảo vệ ý tưởng, nhưng thực tế là Firefox đã triển khai nó mang lại cho bạn điều gì đó để bắt đầu.


Cảm ơn vì điều đó - tôi không nghĩ mình đủ chuyên tâm vào thời điểm này để gửi bản vá. Đó là điều mà bạn có thể sẽ không muốn xảy ra nếu bạn không biết. Nó kinda phá vỡ sandbox trình duyệt ...
Damovisa

4
Nó không phá vỡ hộp cát của trình duyệt, vì bạn đã cố tình chọn tải lên tệp đó; nếu nó có thể truy cập vào máy chủ, nó có thể quay lại trình duyệt, chỉ với một chuyến đi khứ hồi. Với công việc đang tiến hành làm cho chế độ ngoại tuyến hoạt động cho các ứng dụng web, đây sẽ là một tính năng hợp lý.
Brian Campbell

Mm, thực ra đó là một điểm công bằng. Đã có người dùng tương tác để chọn tệp đó. Cảm ơn.
Damovisa

@Damovisa Tôi không biết bạn có còn quan tâm đến điều này hay không, nhưng tôi nghĩ rằng tôi sẽ cập nhật câu trả lời của mình để đề cập đến API tệp mới thực hiện những gì bạn đang tìm kiếm và được triển khai trong Firefox, Chrome và các bản dựng hàng đêm của Safari.
Brian Campbell

Tuyệt vời, cảm ơn vì điều đó. Tôi đã chuyển sang công việc khác, nhưng đó là tốt để biết câu trả lời là có :)
Damovisa

25

Để đọc tệp do người dùng chọn, bằng hộp thoại mở tệp, bạn có thể sử dụng <input type="file">thẻ. Bạn có thể tìm thông tin về nó từ MSDN . Khi tệp được chọn, bạn có thể sử dụng API FileReader để đọc nội dung.

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>


Không hoạt động trong Internet Explorer.
Merwais Muafaq

4

Chúc bạn viết mã vui vẻ!
Nếu bạn gặp lỗi trên Internet Explorer, hãy thay đổi cài đặt bảo mật để cho phép 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;
  }
 }

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.