使用文件对象读取多个文件

Reading multiple files using file object

我正在使用一个文件上传多个文件reader

我的目标是获取每个文件的base64数据作为数组并输出到控制台。但是由于 async

,我的代码总是显示空数组

当所有文件 reader 都被完全读取时,如何显示 base64 数组?

我的代码在这里

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
            <script>
    var file;
    var allfiles = [];

    function uploadForm() {
        Object.keys($('#file')[0].files).forEach(function(f){
          reader = new FileReader()
          console.log("---------")
          reader.readAsDataURL( $('#file')[0].files[f]);
          reader.onloadend = function(e) {
              allfiles.push(e.target.result);
              showMessage("Uploaded")
          };
        });
        console.log(JSON.stringify(allfiles))
        showMessage('Uploading file..<img width="20px;" src="https://c.tenor.com/XK37GfbV0g8AAAAi/loading-cargando.gif"/>');
    }
    
       /* Object.keys(files).forEach(function(f){
          alert(files[f])
          reader.readAsDataURL(files[f]);
        })*/

    function showMessage(e) {
        $('#progress').html(e);
        $('#file').val('');
    }
</script>
    
    
        <table cellpadding="5px">
        <tr>
            <td>Select File:</td>
            <td>
                <input id="file" type="file" value="" accept=".csv,.xlsx,.docx,.rtf,.pdf,.pptx,.txt" multiple>
            </td>
        </tr>
        <tr>
            <td colspan="2"><button onclick="uploadForm(); return false;">Upload</button>&emsp;</td>
        </tr>
        <tr>
            <td colspan="2">
                <div id="progress"></div>
            </td>
        </tr>
    </table>
    

在您的特定情况下,readAsDataURLreader.onloadend 被分配一个侦听器之前完成。重新排序即可解决:

reader.onloadend = function(e) {
    allfiles.push(e.target.result);
    showMessage("Uploaded")
};
reader.readAsDataURL( $('#file')[0].files[f]);

但这不适用于较大的文件(当 readAsDataURL 行为 async 时)。我建议您开始使用 Promises:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
    var file;
    var allfiles = [];

    function loadFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader()
            console.log("---------")
            reader.onerror = reject;
            reader.onload = (e) => resolve(e.target.result);
            reader.readAsDataURL(file);
        })
    }

    function filesToArray(files) {
        const out = [];
        for (let i = 0; i < files.length; ++i) out.push(files[i]);
        return out;
    }

    function uploadForm() {

        const files = filesToArray($('#file')[0].files);
        let uploaded = 0;
        const promises = files.map(async f => {
                const result = await loadFile(f);
                showMessage(`${uploaded ++}/${files.length}`);
                allfiles.push(result);
            });

        showMessage('Uploading file..<img width="20px;" src="https://c.tenor.com/XK37GfbV0g8AAAAi/loading-cargando.gif"/>');
        Promise.all(promises)
            .then(r => {
                console.log(allfiles);
                showMessage('Uploaded');
            })
            .catch(e => showMessage('Failed'));
    }

    function showMessage(e) {
        $('#progress').html(e);
        $('#file').val('');
    }
</script>

<table cellpadding="5px">
    <tr>
        <td>Select File:</td>
        <td>
            <input id="file" type="file" value="" accept=".csv,.xlsx,.docx,.rtf,.pdf,.pptx,.txt" multiple>
        </td>
    </tr>
    <tr>
        <td colspan="2"><button onclick="uploadForm(); return false;">Upload</button>&emsp;</td>
    </tr>
    <tr>
        <td colspan="2">
            <div id="progress"></div>
        </td>
    </tr>
</table>