Membaca konten file di sisi klien dalam javascript di berbagai browser

113

Saya mencoba memberikan solusi khusus skrip untuk membaca konten file di mesin klien melalui browser.

Saya memiliki solusi yang berfungsi dengan Firefox dan Internet Explorer. Ini tidak bagus, tapi saya hanya mencoba hal-hal saat ini:

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

Saya dapat menelepon getFileContents()dan itu akan menulis isinya ke dalam fileContentsarea teks.

Apakah ada cara untuk melakukan ini di browser lain?

Saya paling khawatir dengan Safari dan Chrome saat ini, tetapi saya terbuka untuk saran untuk browser lainnya.

Edit: Menanggapi pertanyaan, "Mengapa Anda ingin melakukan ini?":

Pada dasarnya, saya ingin mencirikan konten file bersama dengan kata sandi satu kali di sisi klien sehingga saya dapat mengirim informasi ini kembali sebagai verifikasi.

Damovisa
sumber
Bukannya saya punya jawaban tapi hanya untuk kejelasan, apakah anda perlu mengetahui lokasi file tersebut? Jika tidak, apakah lokasi file harus dibaca dari input file atau bisa dari textbox / textarea / apapun?
Darko Z
Pertanyaan bagus. Tidak, saya tidak terlalu peduli dari mana file itu berasal, hanya isinya. Menggunakan input file tampaknya masuk akal bagi saya meskipun karena itu html asli - ada satu hal yang harus saya lakukan.
Damovisa
mengapa kamu ingin melakukan ini? server dimaksudkan untuk melakukan itu.
geowa4
Ok, singkatnya: Pengguna memasukkan kata sandi dan memilih file. Kata sandi mendapat hash dengan konten file dan ini dikirim ke server bersama dengan file. Ketika sampai di sana, saya dapat memverifikasi bahwa kata sandi klien yang benar telah digunakan.
Damovisa

Jawaban:

159

Diedit untuk menambahkan informasi tentang File API

Sejak saya pertama kali menulis jawaban ini, API File telah diusulkan sebagai standar dan diterapkan di sebagian besar browser (seperti IE 10, yang menambahkan dukungan untuk FileReaderAPI yang dijelaskan di sini, meskipun belum FileAPI). API ini sedikit lebih rumit daripada Mozilla API yang lebih lama, karena dirancang untuk mendukung pembacaan file asinkron, dukungan yang lebih baik untuk file biner, dan dekode penyandian teks yang berbeda. Ada beberapa dokumentasi yang tersedia di Jaringan Pengembang Mozilla serta berbagai contoh online. Anda akan menggunakannya sebagai berikut:

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

Jawaban asli

Tampaknya tidak ada cara untuk melakukan ini di WebKit (dengan demikian, Safari dan Chrome). Satu-satunya kunci yang dimiliki objek File adalah fileNamedan fileSize. Menurut pesan komit untuk dukungan File dan FileList, ini terinspirasi oleh objek File Mozilla , tetapi tampaknya hanya mendukung sebagian fitur.

Jika Anda ingin mengubahnya, Anda selalu dapat mengirim patch ke proyek WebKit. Kemungkinan lain adalah mengusulkan API Mozilla untuk dimasukkan dalam HTML 5 ; yang WHATWG milis mungkin adalah tempat terbaik untuk melakukan itu. Jika Anda melakukannya, kemungkinan besar akan ada cara lintas browser untuk melakukan ini, setidaknya dalam beberapa tahun mendatang. Tentu saja, mengirimkan tambalan atau proposal untuk dimasukkan ke HTML 5 berarti beberapa pekerjaan mempertahankan gagasan tersebut, tetapi fakta bahwa Firefox sudah menerapkannya memberi Anda sesuatu untuk memulai.

Brian Campbell
sumber
Terima kasih untuk itu - Saya rasa saya tidak cukup berdedikasi pada saat ini untuk mengirimkan tambalan. Itu adalah sesuatu yang Anda mungkin tidak ingin terjadi tanpa sepengetahuan Anda. Ini agak merusak kotak pasir browser ...
Damovisa
4
Itu tidak merusak kotak pasir browser, karena Anda sengaja memilih untuk mengunggah file itu; jika bisa sampai ke server, itu bisa kembali ke browser, hanya dengan perjalanan ekstra. Mengingat pekerjaan yang akan membuat mode offline berfungsi untuk aplikasi web, ini akan menjadi fitur yang masuk akal.
Brian Campbell
Mm, sebenarnya itu poin yang adil. Ada interaksi pengguna untuk memilih file itu. Terima kasih.
Damovisa
@Damovisa Saya tidak tahu apakah Anda masih peduli tentang ini, tetapi saya pikir saya akan memperbarui jawaban saya untuk menyebutkan API File baru yang melakukan apa yang Anda cari, dan diimplementasikan di Firefox, Chrome, dan versi nightly build Safari.
Brian Campbell
Luar biasa, terima kasih untuk itu. Saya telah pindah ke pekerjaan lain, tetapi senang mengetahui jawabannya ada di sana :)
Damovisa
25

Untuk membaca file yang dipilih oleh pengguna, menggunakan dialog buka file, Anda dapat menggunakan <input type="file">tag. Anda dapat menemukan informasi tentangnya dari MSDN . Saat file dipilih, Anda dapat menggunakan API FileReader untuk membaca isinya.

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>

cdiggins.dll
sumber
Tidak berfungsi di Internet Explorer.
Merwais Muafaq
4

Selamat membuat kode!
Jika Anda mendapatkan kesalahan di Internet Explorer, Ubah pengaturan keamanan untuk mengizinkan 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;
  }
 }
Mnyikka
sumber