JS原生之文件上传系列(单文件上传_基于BASE64)

该代码段展示了一个使用JavaScript和FormData实现多文件上传的功能,包括文件选择、上传进度显示、文件移除以及错误处理。通过事件委托处理移除操作,利用Promise.all等待所有文件上传完成并显示结果。
摘要由CSDN通过智能技术生成

第五节:基于formdata实现多文件上传

/* 多文件上传 */
(function () {
    let upload = document.querySelector('#upload5'),
        upload_inp = upload.querySelector('.upload_inp'),
        upload_button_select = upload.querySelector('.upload_button.select'),
        upload_button_upload = upload.querySelector('.upload_button.upload'),
        upload_list = upload.querySelector('.upload_list');
    let _files = [];

    // 验证是否处于可操作性状态
    const checkIsDisable = element => {
        let classList = element.classList;
        return classList.contains('disable') || classList.contains('loading');
    };

    // 把文件上传到服务器
    const changeDisable = flag => {
        if (flag) {
            upload_button_select.classList.add('disable');
            upload_button_upload.classList.add('loading');
            return;
        }
        upload_button_select.classList.remove('disable');
        upload_button_upload.classList.remove('loading');
    };
    upload_button_upload.addEventListener('click', async function () {
        if (checkIsDisable(this)) return;
        //_files是一个类数组集合
        if (_files.length === 0) {
            alert('请您先选择要上传的文件~~');
            return;
        }
        changeDisable(true);
        // 循环发送请求
        //Array.from将类数组转为数组
        let upload_list_arr = Array.from(upload_list.querySelectorAll('li'));
        _files = _files.map(item => {
            let fm = new FormData,
                curLi = upload_list_arr.find(liBox => liBox.getAttribute('key') === item.key),
                curSpan = curLi ? curLi.querySelector('span:nth-last-child(1)') : null;
            fm.append('file', item.file);
            fm.append('filename', item.filename);
            return instance.post('/upload_single', fm, {
                onUploadProgress(ev) {
                    // 检测每一个的上传进度
                    if (curSpan) {
                        curSpan.innerHTML = `${(ev.loaded/ev.total*100).toFixed(2)}%`;
                    }
                }
            }).then(data => {
                if (+data.code === 0) {
                    if (curSpan) {
                        curSpan.innerHTML = `100%`;
                    }
                    return;
                }
                return Promise.reject();
            });
        });

        // 等待所有处理的结果
        Promise.all(_files).then(() => {
            alert('恭喜您,所有文件都上传成功~~');
        }).catch(() => {
            alert('很遗憾,上传过程中出现问题,请您稍后再试~~');
        }).finally(() => {
            changeDisable(false);
            _files = [];
            upload_list.innerHTML = '';
            upload_list.style.display = 'none';
        });
    });

    // 基于事件委托实现移除的操作
    upload_list.addEventListener('click', function (ev) {
        let target = ev.target,
            curLi = null,
            key;
        if (target.tagName === 'EM') {
            curLi = target.parentNode.parentNode;
            if (!curLi) return;
            upload_list.removeChild(curLi);
            key = curLi.getAttribute('key');
            _files = _files.filter(item => item.key !== key);
            if (_files.length === 0) {
                upload_list.style.display = 'none';
            }
        }
    });

    // 获取唯一值
    const createRandom = () => {
        let ran = Math.random() * new Date();
        return ran.toString(16).replace('.', '');
    };
    upload_inp.addEventListener('change', async function () {
        _files = Array.from(upload_inp.files);
        if (_files.length === 0) return;
        // 我们重构集合的数据结构「给每一项设置一个唯一值,作为自定义属性存储到元素上,后期点击删除按钮的时候,我们基于这个自定义属性获取唯一值,再到集合中根据这个唯一值,删除集合中这一项」
        _files = _files.map(file => {
            return {
                file,
                filename: file.name,
                key: createRandom()
            };
        });
        // 绑定数据
        let str = ``;
        _files.forEach((item, index) => {
            str += `<li key="${item.key}">
                <span>文件${index+1}:${item.filename}</span>
                <span><em>移除</em></span>
            </li>`;
        });
        upload_list.innerHTML = str;
        upload_list.style.display = 'block';
    });

    upload_button_select.addEventListener('click', function () {
        if (checkIsDisable(this)) return;
        upload_inp.click();
    });
})();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SKMA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值