美文网首页web前端
js大文件断点续传

js大文件断点续传

作者: 姜治宇 | 来源:发表于2020-03-28 16:52 被阅读0次

以1G的电影为例,断点续传功能的思路是:
1、前端将电影切成1024份小片,每份大小是1m
2、前端将切片文件进行递归上传。
3、后端接收文件,将字节流追加写入upload目录
4、如果打断文件上传,先去后端查询已接收文件的大小,回传给前端
5、slice的start位置更新为断点处,继续上传。
6、后端接收完毕,返回success。
7、前端显示进度100%完成。
思路还是比较清晰的,我们先来做一下前端工作。浏览器提供的File对象有slice切片功能,我们可以根据文件大小切成小片。
前端代码fileupload.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div class="con">
        <input type="file" id="upload" /><br>


        预览:<img id="showPic" src="" style="width:200px;height:200px;" /><br>

        <button onclick="upload()">点击上传</button>

        <progress id="prog" max="100" value="0"></progress>
    </div>

</body>
</html>
<script>
    const chunkSize = 1024 * 1024 //每片大小为1MB
    var fileNode = document.getElementById('upload')//文件
    var progress = document.getElementById('prog')//进度条
    var fileObj;
    fileNode.onchange = function(e){
        fileObj = e.target.files[0]
        var fr = new FileReader()
        fr.readAsDataURL(fileObj)
        fr.onload = function(){
            document.getElementById('showPic').setAttribute('src',fr.result)
        }

    }
    function upload(){

        var fileSize = fileObj.size //文件大小
        var xhr = new XMLHttpRequest()
        //查询起始位置start
        xhr.open('post','/upload/filesize',true)
        xhr.onload = function(){
            if(this.readyState ===4 && this.status === 200) {
                var start = parseInt(this.responseText)

                progress.max = fileSize
                progress.value = start

                //开始上传
                doUpload(start)

            }
        }
        var data = new FormData()
        data.append('filename',fileObj.name)
        xhr.send(data)
    }
    function doUpload(start){
        if(start >= fileObj.size){ //递归,设置退出条件
            return;
        }
        var end = (start + chunkSize > fileObj.size) ? fileObj.size : (start + chunkSize);
        var fd = new FormData()
        fd.append('filename',fileObj.name)
        fd.append('fileData',fileObj.slice(start,end))

        var xhr = new XMLHttpRequest()
        xhr.open('post','/upload/do',true)
        xhr.onload = function(){
            if(this.readyState ===4 && this.status ===200){

                progress.value = end;

                doUpload(end);
            }
        }
        xhr.send(fd)

    }
</script>

前端代码比较简单,主要是计算出切片start和end位置,然后递归调用自身即可。
下面做一下后端,我们需要先搭建一个express服务器。

1、下载安装node
2、安装express
npm install express -g
3、安装express项目生成器
npm install express-generator -g
4、创建工程
express --view=ejs myserver
5、安装依赖包
cd myserver
npm install
npm install multiparty -S
6、运行服务
npm start

因为前端发送的是formdata格式,因此后端需要单独安装multiparty中间件来处理。
当服务器跑起来之后:
1、我们需要把前端代码fileupload.html迁移到public文件夹下面,通过网址http://localhost:3000/fileupload.html访问。
2、在app.js新建一个路由upload。

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var uploadRouter = require('./routes/upload');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/upload', uploadRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

3、在routes下面新增文件夹upload,用来放上传的文件。
4、routes/upload.js:

var express = require('express');
var router = express.Router();
var path = require('path');
var fs = require("fs")
var multiparty = require('multiparty');

var uploadPath = path.join(__dirname, 'upload','/');

router.post('/filesize', function(req, res, next) {
    var form = new multiparty.Form();
    form.parse(req, function(err, fields, files) {

        if(!err){
            var filePath = path.join(uploadPath, fields.filename[0]);
            fs.stat(filePath,function(error,stats){
                console.log(stats)
                if(error){
                    res.send('0')
                }else{
                    res.send(''+stats.size);
                }
            })
        }

    })

});
router.post('/do', function(req, res, next) {
    var form = new multiparty.Form();
    form.parse(req, function(err, fields, files) {
        if(!err){
            console.log(fields)//除文件之外的字段信息
            console.log(files)//文件相关的信息

            var fileData = files.fileData[0]
            var filePath = path.join(uploadPath, fields.filename[0]);

            fs.appendFileSync(filePath, fs.readFileSync(fileData.path));//同步读写数据
            res.send('success')//返回成功状态
        }
    })

});

module.exports = router;
经过测试发现,文件确实是分片上传了: upload.jpg

你可以在上传中途刷新一下页面,然后重新上传该文件,发现进度条仍是从断点处开始上传的。

相关文章

  • js大文件断点续传

    以1G的电影为例,断点续传功能的思路是:1、前端将电影切成1024份小片,每份大小是1m2、前端将切片文件进行递归...

  • IOS 断点续传原理浅析(第一篇)

    断点续传概述: 断点续传就是从文件上次中断的地方开始重新下载或上传数据,当下载大文件的时候,如果没有实现断点续传功...

  • iOS-16 断点续传 下载

    断点续传概述: 断点续传就是从文件上次中断的地方开始重新下载或上传数据,当下载大文件的时候,如果没有实现断点续传功...

  • 大文件断点续传

    对于大文件,往往需要通过断点续传来应对不稳定的网络环境。这几天正好做毕设,记下来断点续传的一些想法 H5断点续传 ...

  • 日常出现疑难问题

    BCompare4注册码 webuploader 大文件分片,断点续传,以及秒传功能 VMware Worksta...

  • 有关文件上传(未完待续)

    分片:将一个完整的大文件按照一定的规则切分成多个小的片段,方便后续的并发处理和断点续传。断点续传:当因为环境因素,...

  • vue-simple-uploader组件的一些使用心得

    前言 因为项目需要上传大文件,考虑使用分片上传、断点续传这些功能故选用vue-simple-uploader,期间...

  • Linux_285_Rsync断点续传

    rsync支持大文件断点续传rsync提供了如下的参数--partial默认情况下,rsync传输中断后,将会删除...

  • 大文件断点续传

    spark-MD5 增量计算切片 npm i spark-md5https://github.com/satazo...

  • java大文件断点续传

    上传大文件经常遇到上传一半由于网络或者其他一些原因上传失败。然后又得重新上传(很麻烦),所以就想能不能做个断点上传...

网友评论

    本文标题:js大文件断点续传

    本文链接:https://www.haomeiwen.com/subject/mstluhtx.html