AJAX+PHP 实现大文件上传功能 附加demo

在工作中经常会遇到一些大文件上传的需求,可能是图片,压缩包,视频,安装包等等,那如果涉及到大文件上传,我们应该怎么办呢?接下来就通过分析+代码展示给大家提供一些方向.

一、思路分析

将文件切割成若干个不同的小文件上传到服务端,由服务端进行文件的合并以及移动.

这里的话需要了解slice(),文件切割主要需要用到的方法.
在这里插入图片描述
注意记得去php配置调整文件上传大小

二、案例展示

  • 前端页面部分
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>demo<在这里插入代码片/title>
</head>
<link rel="stylesheet" href="js/layui/css/layui.css">
<style type="text/css">
    #file {
        position: absolute;
        left: 0;
        top: 0;
        padding: 0;
        margin: 0;
        height: 132px;
        opacity: 0;
        width: 362px
    }
</style>
<body>

    <div class="layui-input-inline layui-upload-drag" style="width: 300px">
        <input type="file" id="file">
        <i class="layui-icon"></i>
        <p>点击图标上传,或将文件拖拽到此处</p>
        <div class="" id="uploadDemoView">
        <span>未选择文件</span>
        </div>
    </div>
    <div class="layui-progress layui-progress-big" lay-showpercent="true" lay-filter="demo" style="margin-top: 20px;width: 362px">
      <div class="layui-progress-bar layui-bg-red" lay-percent="0" id="demo"></div>
    </div>
    <div style="margin-top: 25px;width: 300px;text-align: center;">
        <button type="button" class="layui-btn layui-btn-normal" id="upload">上传</button>
        <!-- 偷懒 -->
        <a href="" type="button" class="layui-btn layui-btn-primary">清空</a>
    </div>
    <script src="js/layui/layui.all.js"></script>
    <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
    <script>
        var element = '';
        layui.use('element', function(){
          element = layui.element;
        });
        //上传功能
        $("#upload").click(function(){
            //文件对象
            var file = $("#file")[0].files[0];
            var qp = {};
            if (file == undefined) {
                layer.msg('请先选择文件');
                return;
            }
            var file_name = file.name;                      //文件名
            var file_size = file.size;                      //文件总大小
            var succeed = 0;                                //请求成功次数
            var shardSize = 10485760;                       //10M分片大小单位字节 记得去php配置调整文件大小
            var shardCount = Math.ceil(file_size/shardSize);//总片数
            var rate = 1/shardCount*100;                    //进度条
            for (var i = 0; i < shardCount; i++) {
                var start = i * shardSize;                  // 计算每一片数据的起始与结束位置              
                var end = Math.min(file_size, start + shardSize);
                var form = new FormData();
                var loading = '';
                form.append("data", file.slice(start, end));    //切片数据
                form.append("file_name", file_name);                      
                form.append("total", shardCount);               // 总片数
                form.append("index", i + 1);                    // 当前是第几片
                // Ajax提交
                $.ajax({
                    url: "UploadBigFile.php?act=upload",
                    type: "POST",
                    data: form,
                    async: true,
                    processData: false,
                    dataType : "json",
                    contentType: false, 
                    beforeSend: function(){
                        loading = layer.msg('文件上传中请稍等', {
                          icon: 16
                          ,shade: 0.11
                          ,time:888888
                        });
                    },
                    success: function(data){
                        if (data.errno == 10000) {
                            succeed ++;
                            element.progress('demo', (succeed*rate).toFixed(2)+'%');
                            if (succeed == shardCount) {
                                qp.total = shardCount;
                                qp.file_name = file_name;
                                layer.close(loading);
                                $.ajax({
                                    url: "UploadBigFile.php?act=join",
                                    type: "POST",
                                    data: qp,
                                    beforeSend: function(){
                                        loading = layer.msg('等待文件合并', {
                                          icon: 16
                                          ,shade: 0.11
                                          ,time:888888
                                        });
                                    },
                                    success: function(data){
                                        if (data.code == 10000) {
                                            layer.open({content: '上传成功', time: 1000});
                                            setTimeout(function(){
                                            }, 2000);
                                        } else {
                                            layer.open({content: '上传失败', time: 2});
                                            setTimeout(function(){
                                                location.reload();
                                            }, 2000);
                                        }
                                    }
                                });
                            }
                        } else {
                            layer.open({content: '上传失败', time: 2});
                            setTimeout(function(){
                                location.reload();
                            }, 2000);
                        }
                    }
                });
            }

        });
        //获取文件名
        $('#file').change(function(){
            var file = document.getElementById("file").files;  
            $('#uploadDemoView').find('span').text('已选择: '+file[0]['name']);
        });
    </script>
</body>
</html>
  • 后端页面部分
<?php
$name       = strstr($_POST['file_name'],'.',1);//文件名称
$act        = $_GET['act'];
$path       = "./upload/";
$ext_suffix = substr($_POST['file_name'],strripos($_POST['file_name'],".")+1);//文件后缀

if ($act == 'upload') {
    $index = $_POST['index'];//当前片数
    $filename = $path."$index".$name.'.'.$ext_suffix;
    //断点上传已经存在的就跳过
    $result = move_uploaded_file($_FILES['data']['tmp_name'], $filename);
    if ($result) {
        echo json_encode(array('errno'=>10000, 'message'=>'ok'));
    } else {
        echo json_encode(array('errno'=>10001, 'message'=>'上传失败'));
    }
    
} elseif ($_GET['act'] == 'join') {
    $total = intval($_POST['total']);
    @unlink(iconv('UTF-8', 'GBK', $path.$name.'.'.$ext_suffix));
    for($i = 1; $i<=$total; $i++){
         file_put_contents($path.iconv('UTF-8', 'GBK',$name.'.'.$ext_suffix), file_get_contents(iconv('UTF-8', 'GBK', $path."$i".$name.'.'.$ext_suffix)), FILE_APPEND);
        @unlink(iconv('UTF-8', 'GBK', $path."$i".$name.'.'.$ext_suffix));
    }
    echo json_encode(array('errno'=>10000, 'message'=>'上传成功'));    
}

主要代码部分的话已经贴到该文章中,一些引入文件夹部分需要自己创建,我已经在demo压缩包上传到资源中,等审核通过后会附在文章上面.

demo下载(关注后就可以免费下载)

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值