1.H5上传文件 #

选中文件后并显示文件信息,比如文件名,类型,尺寸 一个能够显示真实的进度条 上传的速度 剩余时间的预估 已上传的量 上传结束后服务器返回上传图片并在页面显示出来

1.1 基本界面 #

引入bootstrap

<div class="container">
    <form>
        <div class="form-group">
            <label>请选择上传的文件</label>
            <input class="form-control fileUpload" type="file" onchange="fileSelect()" name="fileUpload">
        </div>
        <div class="form-group">
            <input type="button" class="btn btn-primary" onclick="uploadFile()" value="提交">
        </div>
        <div>
            <table class="table table-bordered">
                <tr>
                    <td>文件名</td>
                    <td>文件大小</td>
                    <td>文件类型</td>
                </tr>
                <tr>
                    <td class="fileName"></td>
                    <td class="fileSize"></td>
                    <td class="fileType"></td>
                </tr>
            </table>
        </div>
    </form>
</div>

1.2 后台服务 #

var mime = require('mime');
var http = require('http');
var util = require('util');
var url = require('url');
var fs = require('fs');
var querystring = require('querystring');
var app = http.createServer(function (req,res) {
    var urlObj = url.parse(req.url,true);
    var pathname = urlObj.pathname;
    if(pathname=='/'){
        fs.createReadStream('./index.html').pipe(res);
    }else if(pathname=='/post'){
        //此处为上传使用
    }else{
        res.end('404');
    }
}).listen(8080);

1.3 选择文件显示详细信息 #

function fileSelect(){
    var file = document.querySelector('.fileUpload').files[0];
    if(file){
        var fileSize = 0;
        document.querySelector('.fileName').innerHTML = file.name;
        document.querySelector('.fileSize').innerHTML = file.size;
        document.querySelector('.fileType').innerHTML = file.type;
    }
}

1.4 formData上传 #

 function uploadFile(){
    var fd = new FormData();
    var file = document.querySelector('.fileUpload').files[0];
    fd.append('fileUpload',file);
    var xhr = new XMLHttpRequest();
    xhr.upload.addEventListener('progress',process,false); //上传监听过程
    xhr.addEventListener('load',success,false);//上传成功
    xhr.addEventListener('error',error,false);//上传出错
    xhr.addEventListener('abort',abort,false);//上传退出
    xhr.open('POST','/post');
    xhr.send(fd);
}

1.5 增加上传监听函数 #

var progress = success = error = abort = function () {};
var progress = function(event){
    var percent = Math.round(event.loaded*100/event.total);//上传的进度
    document.querySelector('.progress-bar').style.width = percent+'%';
    document.querySelector('.progress-bar')["aria-valuenow"]= percent;
}

1.6 增加进度条代码 #

<div class="progress">
    <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
    </div>
</div>

1.7 增加后台接收代码 #

var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {

});

1.8 增加单位格式化 #

function change (size){
        var fileSize = 0;
        if(size > 1024*1024){
            fileSize = Math.round(size/(1024*1024)) + 'MB';
        }else{
            fileSize = Math.round(size/(1024)) + 'kb';
        }
        return fileSize;
}

1.9 计算进度 #

var diff = event.loaded - last;
        last = event.loaded;
        //当前速度
        document.querySelector('.speed').innerHTML = change(diff);
        document.querySelector('.stage').innerHTML = change(event.loaded);
        document.querySelector('.remaining').innerHTML = ((event.total-event.loaded)/diff).toFixed(0)+'秒';

C:\Users\10354_000\AppData\Local\Temp清除缓存

1.10 接收上传数据 #

var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
    console.log(files.fileUpload);
    fs.createReadStream(files.fileUpload.path).pipe(fs.createWriteStream('./'+files.fileUpload.name));
});

2.分片上传 #

2.1 上传文件 #

function uploadFile(){
        var file = document.querySelector('.fileUpload').files[0];
        var sharedSize = 10 * 1024 * 1024;
        var sharedCount =Math.ceil(file.size/sharedSize);
        for(var i = 0; i<sharedCount;i++){
            var fd = new FormData();
            var start = i*sharedSize;
            var end = Math.min(file.size,start+sharedSize);
            fd.append('data',file.slice(start,end));
            fd.append('name','upload.psd');
            fd.append('total',sharedCount);
            fd.append('index',i+1);
            fd.append('size',sharedSize);
            var xhr = new XMLHttpRequest();
            xhr.open('POST','/post');
            xhr.send(fd);
        }
}

2.2 server修改 #

form.parse(req, function(err, fields, files) {
    var filename = fields.name;
    var index = fields.index;
    var total = fields.total;
    var size = fields.size;
    var src = fs.createReadStream(files.data.path);
    var target =fs.createWriteStream(filename+'.'+index);
    src.pipe(target);
    target.on('close', function () {
        if(successCount == total -1){
            var fd = fs.openSync(filename,'a');
            var files = fs.readdirSync('.');
            files.forEach(function (files) {
                if(files.startsWith(filename+'.')){
                    var pos = Number(path.extname(files).slice(1)-1)*size;
                    var buff = fs.readFileSync(files);
                    fs.writeSync(fd,buff,0,buff.length,pos);
                    fs.unlinkSync(files);
                }
            });
            fs.closeSync(fd);
            successCount=0;
        }else{
            successCount++;
        }
    });
    res.end('ok');
});