การอ่านเนื้อหาไฟล์บนฝั่งไคลเอ็นต์ในจาวาสคริปต์ในเบราว์เซอร์ต่างๆ


113

ฉันกำลังพยายามจัดหาโซลูชันสำหรับสคริปต์เท่านั้นสำหรับการอ่านเนื้อหาของไฟล์บนเครื่องไคลเอนต์ผ่านเบราว์เซอร์

ฉันมีโซลูชันที่ใช้ได้กับ 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 ในขณะนี้ แต่ฉันเปิดรับคำแนะนำสำหรับเบราว์เซอร์อื่น ๆ

แก้ไข:ในการตอบคำถาม "ทำไมคุณถึงต้องการทำสิ่งนี้":

โดยพื้นฐานแล้วฉันต้องการแฮชเนื้อหาไฟล์พร้อมกับรหัสผ่านแบบใช้ครั้งเดียวในฝั่งไคลเอ็นต์เพื่อที่ฉันจะได้ส่งข้อมูลนี้กลับเป็นการยืนยัน


ไม่ใช่ว่าฉันมีคำตอบ แต่เพื่อความชัดเจนคุณจำเป็นต้องรู้ตำแหน่งของไฟล์หรือไม่? ถ้าไม่ตำแหน่งของไฟล์จะต้องอ่านจากอินพุตไฟล์หรืออาจเป็น textbox / textarea / อะไรก็ได้?
Darko Z

คำถามที่ดี. ไม่ฉันไม่สนใจว่าไฟล์มาจากไหนมี แต่เนื้อหาเท่านั้น การใช้การป้อนไฟล์ดูเหมือนจะสมเหตุสมผลสำหรับฉันแม้ว่าจะเป็น html ดั้งเดิม - มีสิ่งหนึ่งที่ฉันต้องทำน้อยกว่า
Damovisa

ทำไมคุณถึงต้องการทำสิ่งนี้? เซิร์ฟเวอร์ตั้งใจจะทำเช่นนั้น
geowa4

ตกลงกล่าวโดยย่อ: ผู้ใช้ป้อนรหัสผ่านและเลือกไฟล์ รหัสผ่านถูกแฮชพร้อมกับเนื้อหาของไฟล์และจะถูกส่งไปยังเซิร์ฟเวอร์พร้อมกับไฟล์ เมื่อไปถึงที่นั่นฉันสามารถตรวจสอบได้ว่าใช้รหัสผ่านไคลเอนต์ที่ถูกต้อง
Damovisa

คำตอบ:


159

แก้ไขเพื่อเพิ่มข้อมูลเกี่ยวกับ File API

ตั้งแต่แรกที่ฉันเขียนคำตอบนี้File APIจึงได้รับการเสนอให้เป็นมาตรฐานและนำไปใช้ในเบราว์เซอร์ส่วนใหญ่ (ณ IE 10 ซึ่งเพิ่มการรองรับFileReaderAPI ที่อธิบายไว้ที่นี่แม้ว่าจะยังไม่ใช่FileAPI ก็ตาม) API มีความซับซ้อนกว่า Mozilla API รุ่นเก่าเล็กน้อยเนื่องจากออกแบบมาเพื่อรองรับการอ่านไฟล์แบบอะซิงโครนัสรองรับไฟล์ไบนารีและการถอดรหัสการเข้ารหัสข้อความที่แตกต่างกันได้ดีขึ้น มีเอกสารบางอย่างอยู่ใน Mozilla Developer Networkรวมถึงตัวอย่างต่างๆทางออนไลน์ คุณจะใช้มันดังนี้:

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) ปุ่มเดียวที่ไฟล์วัตถุมีอยู่และfileName fileSizeตามข้อความคอมมิตสำหรับการสนับสนุน File และ FileList สิ่งเหล่านี้ได้รับแรงบันดาลใจจากอ็อบเจ็กต์ File ของ Mozillaแต่ดูเหมือนว่าจะรองรับเฉพาะบางส่วนของคุณสมบัติเท่านั้น

หากคุณต้องการเปลี่ยนแปลงสิ่งนี้คุณสามารถส่งโปรแกรมแก้ไขไปที่โครงการ WebKit ได้ตลอดเวลา เป็นไปได้ก็จะเสนอ Mozilla API สำหรับการรวมอยู่ในHTML 5 ; WHATWGรายชื่อผู้รับจดหมายอาจจะเป็นสถานที่ที่ดีที่สุดที่จะทำเช่นนั้น หากคุณทำเช่นนั้นก็มีโอกาสมากขึ้นที่จะมีวิธีข้ามเบราว์เซอร์ในการทำเช่นนี้อย่างน้อยก็ในเวลาสองสามปี แน่นอนว่าการส่งแพตช์หรือข้อเสนอเพื่อรวมไว้ใน HTML 5 นั้นหมายถึงงานบางอย่างที่ปกป้องแนวคิดนี้ แต่ความจริงที่ว่า Firefox ดำเนินการไปแล้วนั้นจะช่วยให้คุณเริ่มต้นได้


ขอบคุณสำหรับสิ่งนั้น - ฉันคิดว่าฉันไม่ทุ่มเทมากพอในตอนนี้ที่จะส่งแพตช์ เป็นสิ่งที่คุณอาจไม่ต้องการให้เกิดขึ้นโดยที่คุณไม่รู้ตัว มันทำลายแซนด์บ็อกซ์ของเบราว์เซอร์ ...
Damovisa

4
มันไม่ทำลายแซนด์บ็อกซ์ของเบราว์เซอร์เนื่องจากคุณจงใจเลือกที่จะอัปโหลดไฟล์นั้น หากสามารถเข้าถึงเซิร์ฟเวอร์ได้ก็สามารถกลับไปที่เบราว์เซอร์ได้เพียงแค่มีการเดินทางรอบพิเศษ เนื่องจากงานที่กำลังจะทำให้โหมดออฟไลน์ทำงานได้สำหรับเว็บแอปนี่จะเป็นคุณสมบัติที่สมเหตุสมผล
Brian Campbell

อืมนั่นเป็นจุดที่ยุติธรรม มีการโต้ตอบกับผู้ใช้เพื่อเลือกไฟล์นั้น ขอบคุณ.
Damovisa

@Damovisa ฉันไม่รู้ว่าคุณยังสนใจเรื่องนี้อยู่หรือเปล่า แต่ฉันคิดว่าฉันจะอัปเดตคำตอบเพื่อพูดถึง File API ใหม่ที่ทำในสิ่งที่คุณกำลังมองหาและนำไปใช้ใน Firefox, Chrome และงานสร้างทุกคืน Safari
Brian Campbell

1
ไม่ควรแนบตัวจัดการเหตุการณ์ก่อนที่จะโทรreadAsText?
goofballLogic

25

ในการอ่านไฟล์ที่ผู้ใช้เลือกโดยใช้กล่องโต้ตอบเปิดไฟล์คุณสามารถใช้<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;
  }
 }

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.