• node.js分片上传文件


    前端 :

    <html>
    
    <head>
        <title>分片上传文件</title>
    </head>
    
    <body>
        <div class="hei-bg" style="display:block;">
            <div class="user-info" style="display:block;">
                <div class="tc">请上传大文件</div>
                <div class="user-pic picw320">
                    <input id="uppic" type="file">
                </div>
                <div id="jd" class="jdb">进度</div>
    
                <div>
                    <input type="button" value="确定" id="userbtn" class="bg-main tc userbtn">
                </div>
            </div>
        </div>
    </body>
    <script src="/javascripts/jquery.min.js"></script>
    <script>
        $(function () {
            $('#userbtn').on('click', async function () {
                var d1 = new Date();
                let file = $("#uppic")[0].files[0], //上传文件主体
                    name = file.name, //文件名
                    size = file.size, //总大小
                    succeed = 0, //当前上传数
                    shardSize = 1 * 1024 * 1024, //以1MB为一个分片
                    shardCount = Math.ceil(size / shardSize); //总片数
    
                let attr = [];
                try {
                    for (let item = 0; item < shardCount; ++item) {
                        await fn(item); //同步
                        // attr.push(fn(item)); //异步
                    }
                    await Promise.all(attr); //异步
    
                    $('.jdb').append(' 上传成功');
                    var d2 = new Date();
                    console.log(parseInt(d2 - d1) / 1000);
                } catch (err) {
                    $('.jdb').html(err);
                    console.log(err);
                }
    
                function fn(item) {
                    return new Promise((resolve, reject) => {
                        var i = item;
                        var start = i * shardSize, //当前分片开始下标
                            end = Math.min(size, start + shardSize); //结束下标
    
                        //构造一个表单,FormData是HTML5新增的
                        var form = new FormData();
                        form.append("data", file.slice(start, end)); //slice方法用于切出文件的一部分
                        form.append("name", name); //文件名字
                        form.append("total", shardCount); //总片数
                        form.append("index", i + 1); //当前片数
                        //Ajax提交
    
                        $.ajax({
                            url: "/sliceUpload",
                            type: "POST",
                            data: form,
                            timeout: 120 * 1000,
                            async: false, //同步
                            processData: false, //很重要,告诉jquery不要对form进行处理
                            contentType: false, //很重要,指定为false才能形成正确的Content-Type
                            success: function (data) {
                                ++succeed;
                                if (typeof (data) == 'string') {
                                    try {
                                        data = JSON.parse(data);
                                        console.log(data.msg);
                                    } catch (e) {
                                        console.log(data);
                                    }
                                }
                                //生成当前进度百分比
                                var jd = `${Math.round(succeed / shardCount * 100)}%`;
                                $('.jdb').html(jd);
                                /*如果是线上,去掉定时,直接callback(),
                                这样写是为方便,本地测试看到进度条变化
                                因为本地做上传测试是秒传,没有时间等待*/
                                setTimeout(resolve, 50);
                            }
                        });
                    })
                }
            });
        });
    </script>
    
    </html>

    服务器端:

    async function sliceUpload(req, res) {
        var fs = require('fs');
        var multiparty = require('multiparty'); //文件上传模块
        var form = new multiparty.Form(); //新建表单
        //设置编辑
        form.encoding = 'utf-8';
        //设置文件存储路径
        form.uploadDir = "temp/"; // "Uploads/";
        //设置单文件大小限制
        // form.maxFilesSize = 200 * 1024 * 1024;
        /*form.parse表单解析函数,fields是生成数组用获传过参数,files是bolb文件名称和路径*/
        try {
            let [fields, files] = await new Promise((resolve, reject) => {
                form.parse(req, (err, fields, files) => {
                    if (err) reject('test err');
                    resolve([fields, files]);
                })
            })
    
            files = files['data'][0]; //获取bolb文件
            var index = fields['index'][0]; //当前片数
            var total = fields['total'][0]; //总片数
            var name = fields['name'][0]; //文件名称
            var url = 'temp/' + name + index; //临时bolb文件新名字
            fs.renameSync(files.path, url); //修改临时文件名字
    
            var pathname = 'Uploads/' + name; //上传文件存放位置和名称
            if (index == total) { //当最后一个分片上传成功,进行合并
                // 检查文件是存在,如果存在,重新设置名称
                let NonExist = await new Promise((resolve, reject) => {
                    fs.access(pathname, fs.F_OK, (err) => {
                        resolve(err);
                    });
                })
                if (!NonExist) {
                    var myDate = Date.now();
                    pathname = 'Uploads/' + myDate + name;
                }
                logs.info('上传文件:' + pathname);
                /*进行合并文件,先创建可写流,再把所有BOLB文件读出来,
                    流入可写流,生成文件
                    fs.createWriteStream创建可写流   
                    aname是存放所有生成bolb文件路径数组:
                    ['Uploads/3G.rar1','Uploads/3G.rar2',...]
                */
                var writeStream = fs.createWriteStream(pathname);
                var aname = [];
                for (let i = 1; i <= total; i++) {
                    let url = 'temp/' + name + i;
                    let data = await new Promise(function (resolve, reject) {
                        fs.readFile(url, function (error, data) {
                            if (error) reject(error);
                            resolve(data);
                        });
                    });
                    //把数据写入流里
                    writeStream.write(data);
                    //删除生成临时bolb文件              
                    fs.unlink(url, () => {});
                }
                writeStream.end();
                //返回给客服端,上传成功
                var data = JSON.stringify({
                    'code': 0,
                    'msg': '上传成功'
                });
                res.send(data); //返回数据    
            } else { //还没有上传文件,请继续上传
                var data = JSON.stringify({
                    'code': 1,
                    'msg': '继续上传'
                });
                res.send(data); //返回数据    
            }
        } catch (e) {
            logs.info(e);
            res.send(e); //返回数据    
        }
    }
  • 相关阅读:
    返回到上一页的html代码的几种写法
    记一次网站服务器内存占用过多问题
    rpm命令数据库修复日志
    Linux vmstat命令实战详解
    innodb的innodb_buffer_pool_size和MyISAM的key_buffer_size
    mysql
    如何查看linux系统下的各种日志文件 linux 系统日志的分析大全
    /var/lock/subsys作用
    CentOS目录结构详解
    MySQL体系结构
  • 原文地址:https://www.cnblogs.com/xbblogs/p/9072808.html
Copyright © 2020-2023  润新知