Git Product home page Git Product logo

uploadfile's Introduction

文件上传

npm run start   # 启动前端
npm run server  # 启动后端

单个文件上传 form-data

主要是利用js form表单方式进行上传

    let formData = new FormData();
    formData.append('file', _file);
    formData.append('filename', _file.name);
    instance
        .post('/upload_single', formData)
        .then((res) => {
            const { code } = res;
            if (code === 0) {
                alert('file 上传成功');
                return;
            }
            console.log(res);
            return Promise.reject(data.codeText);
        })
        .catch((e) => {
            console.log(e);
        });

单个文件上传 base64

// 利用FildReader 得到文件的base64
/**
 * FileReader.readAsDataURL()开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的Base64字符串以表示所读取文件的内容。
 * **/
const getFileBase64 = (file) => {
    return new Promise((resolve) => {
        let fileReader = new FileReader();
        fileReader.readAsDataURL(file);
        fileReader.onload = (e) => {
            resolve(e.target.result);
        };
    });
};

base64 = await getFileBase64(file);
upload_input.value = ''; // 用于初始化input
try {
    const data = await instance.post(
        '/upload_single_base64',
        {
            file: encodeURIComponent(base64), // 防止乱码问题  decodeURIComponent 对应
            filename: file.name,
        },
        {
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        }
    );

    const { code } = data;
    if (code === 0) {
        alert('文件上传成功!');
    }
    throw data.codeText; // 抛出异常
} catch (e) {
    // 文件上传错误
} finally {
    //
}

单个文件上传 图片缩略图, 客户端自定义名字

/**
 *
 * @param {} file
 * @returns
 * 根据内容生成hash名字
 */
//  SparkMD5 生成HASH
const getBufferByFile = (file) => {
    return new Promise((resolve) => {
        let fileReader = new FileReader();
        fileReader.readAsArrayBuffer(file);
        fileReader.onload = (e) => {
            let buffer = e.target.result;
            console.log(buffer);
            const spark = new SparkMD5.ArrayBuffer();
            spark.append(buffer);
            const HASH = spark.end();
            const suffix = /\.([0-9a-zA-Z]+)$/.exec(file.name)[1];
            console.log(HASH);
            resolve({
                buffer,
                HASH,
                suffix,
                filename: `${HASH}.${suffix}`,
            });
        };
    });
};
// 缩略图,可以用base64 来展示
const base64 = await getFileBase64(file);

const { filename } = await getFileBase64(_file);
    let formData = new FormData();
    formData.append('file', _file);
    formData.append('filename', filename); // 处理名字,服务端不提供名字编译
    instance
        .post('/upload_single_name', formData)
        .then((res) => {
            const { code } = res;
            if (code === 0) {
                alert('file 上传成功');
                return;
            }
            console.log(res);
            return Promise.reject(data.codeText);
        })
        .catch((e) => {
            console.log(e);
        });
});

单个文件上传 进度条管控

上传进度,主要是靠axios中回调

try {
    let formData = new FormData();
    formData.append('file', file);
    formData.append('filename', file.filename);
    const data = await instance.post('/upload_single', formData, {
        // onPuloadProgress; 变化来更新进度
        onUploadProgress: (e) => {
            console.log(e);
            const { loaded, total } = e;
            console.log(
                `${(loaded / total) * 100}%`,
                ' `${loaded/total*100}%`'
            );
            upload_progress.style.display = 'block';
            upload_progrees_value.style.width = `${
                (loaded / total) * 100
            }%`;
        },
    });
    const { code } = data;
    if (code === 0) {
        upload_progrees_value.style.width = `100%`;
        alert('文件上传成功!');
        return;
    }
    throw data.codeText;
} catch (e) {
    //
    console.log(e);
    alert('文件上传失败');
} finally {
    this.value = '';
}

多个文件上传 进度条管控

主要是对上传列表做一个遍历上传。 结合Promise.all() 表示是否全部上传成功!

const _files = files.map((item) => {
    const fm = new FormData();
    const curLi = upload_list_arr.find(
        (liBox) => liBox.getAttribute('key') === item.key
    );
    const 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(e) {
                // 监听每一个上传进度
                const { loaded, total } = e;
                const progress = `${((loaded / total) * 100).toFixed(
                    2
                )}%`;
                if (curSpan) {
                    curSpan.innerText = progress;
                }
            },
        })
        .then((data) => {
            const { code } = data;
            if (code === 0) {
                if (curSpan) {
                    curSpan.innerText = '100%';
                }
                return Promise.resolve(data);
            }
            return Promise.reject(data.codeText);
        });
});
Promise.all(_files).then((res) => {
    console.log(res);
    alert('上传成功');
});

拖拽上传3

拖拽上传没有什么特殊的, 值得注意的是, drop 中的事件参数回携带 dataTransfer, 里面包含着 files。,提取出来,走上传即可!

// 拖拽进入
dragBox.addEventListener('dragenter', function (e) {
    // console.log('拖拽进入')
    e.preventDefault();
    this.style.border = '1px solid red';
});

// 拖拽放下
dragBox.addEventListener('drop', function (e) {
    e.preventDefault();
    this.style.border = '';
    const {
        dataTransfer: { files },
    } = e;
    const file = files[0];
    uploadFile(file);
});

dragBox.addEventListener('dragover', function (e) {
    e.preventDefault();
});

切片上传

切片上传相对于上面,复杂一些, 当然也没有想象中的难!

  1. 上传文件
  2. 利用Bole.prototype.slice() 方法对文件进行切片, 对每一个文件进行HASH 唯一标识
  3. 从服务器获取已经上传的切片,判断是否有些切片已经上传
  4. 上传切片
  5. 上传完切片,通知服务端合并切片
 upload_button_upload.addEventListener('click', async function () {
    // 点击开始上传
    let chunkList = [];
    let alreadyChunkList = [];
    console.log(_file);
    let maxSize = 1024 * 1024;
    let maxCount = Math.ceil(_file.size / maxSize); // 最大允许分割的切片数量为30
    let index = 0;
    if (!_file) return alert('请先选择图片');
    const { HASH, suffix } = await changeBuffer(_file);
    // 判断当前文件可以切出多少切片
    if (maxCount > 10) {
        // 如果切片数量大于最大值
        maxSize = _file.size / 10; // 则改变切片大小
        maxCount = 10;
    }
    console.log(maxCount, 'maxCount');
    console.log(maxSize, 'maxSize');
    while (index < maxCount) {
        chunkList.push({
            file: _file.slice(index * maxSize, (index + 1) * maxSize),
            filename: `${HASH}_${index + 1}.${suffix}`,
        });
        index++;
    }

    // 先获取已经上传的切片
    const data = await instance.post(
        '/upload_already',
        {
            HASH: HASH,
        },
        {
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        }
    );
    index = 0
    const complate = async () => {
        index++;
        let progress = `(${index}/${maxCount})%` // 进度条
        if (index >= maxCount) {
            console.log('ok, 切片完成')
        }
    }

    const { fileList } = data;
    alreadyChunkList = fileList
    console.log(chunkList, 'chunkList');
    chunkList = chunkList.map((item) => {
        if (alreadyChunkList.length > 0 && alreadyChunkList.includes(item.filename)) {
            debugger
            // 表示切片已经存在
            complate()
            return;
        }

        const fm = new FormData();
        fm.append('file', item.file);
        fm.append('filename', item.filename);
        return new Promise((sovle) => {
            instance
                .post('/upload_chunk', fm)
                .then(() => {
                    complate()
                    sovle();
                })
                .catch(() => {
                    //
                });
        });
    });
    Promise.all(chunkList).then(() => {
        instance
            .post(
                '/upload_merge',
                {
                    HASH: HASH,
                    count: maxCount,
                },
                {
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded',
                    },
                }
            )
            .then((res) => {
                console.log('ok');
            });
    });
});

uploadfile's People

Contributors

yaogengzhu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.