多线程文件分片上传

文件上传方法

/// <summary>
    /// 上传公共类
    /// </summary>
    public class UploadFile
    {
        #region 变量
        /// <summary>
        /// 起始位置
        /// </summary>
        long Begin;
        /// <summary>
        /// 结束位置
        /// </summary>
        long End;
        /// <summary>
        /// 每次上传的容量
        /// </summary>
        long size;

        /// <summary>
        /// 下载文件的大小
        /// </summary>
        public long FileSize;

        public string FileUrl;

        /// <summary>
        /// 是否暂停线程
        /// </summary>
        bool isRunning = true;

        //下载状态
        private UploadStatus status;

        /// <summary>
        /// 每次下载容量
        /// </summary>
        long DownloadCapacity;

        /// <summary>
        /// 下载已耗时
        /// </summary>
        private TimeSpan useTime;

        /// <summary>
        /// 最后一次下载时间
        /// </summary>
        private DateTime lastStartTime;

        /// <summary>
        /// 预计下载总耗时
        /// </summary>
        private TimeSpan allTime;

        /// <summary>
        /// 上一秒时已下载总大小
        /// </summary>
        private long BeforSecondUploadSize;

        /// <summary>
        /// 已下载大小
        /// </summary>
        private long UploadSize = 0;

        /// <summary>
        /// 当前下载速度
        /// </summary>
        private double speed;
        /// <summary>
        /// 是否上传完毕
        /// </summary>
        bool iscomplete = false;

        System.Timers.Timer t = new System.Timers.Timer();

        Task task;
        CancellationTokenSource cancelTokenSource = new CancellationTokenSource();

        public string parentFolderId { get; set; }
        /// <summary>
        /// 任务ID
        /// </summary>
        public string taskID { get; set; }
        /// <summary>
        /// 任务文档ID
        /// </summary>
        public string taskDocId { get; set; }
        /// <summary>
        /// 通用文档树文件夹ID
        /// </summary>
        public string folderId { get; set; }
        /// <summary>
        /// 通用文档根节点ID(第一级目录)
        /// </summary>
        public string docListId { get; set; }
        /// <summary>
        /// 上传或者更新文件类型,0为:作业文档;1为:通用文档;2为:问题文档;3为:工作流文档
        /// </summary>
        public int docType { get; set; }
        /// <summary>
        /// 上传类型,0为:上传;1为:更新
        /// </summary>
        public int opType { get; set; }

        UplpadDetectionFileDto detectionDto = new UplpadDetectionFileDto();
        #endregion

        #region 启动上传
        /// <summary>
        /// 启动上传
        /// </summary>
        /// <param name="UploadUrl">上传的URL</param>
        /// <param name="DetectionUrl">检测文件的URL</param>
        public void Startup(string UploadUrl, string DetectionUrl, UplpadDetectionFileDto DetectionDto)
        {
            if (this.status == UploadStatus.Idle)
            {
                MessageUtil.ShowError("只有空闲中才能上传!");
                return;
            }
            //与webapi通信,传递文件信息
            UplpadDetection Detection = WebCommunication.JsonRequestServiceToObject<UplpadDetection>(DetectionUrl, DetectionDto, CommonInfo.Ticike);
            if (Detection.rsCode == "S10000")
            {
                if (Detection.Isexist == true)
                {
                    Begin = Detection.StartingValue;
                }
                else
                {
                    Begin = 0;
                }
            }
            else
            {
                MessageUtil.ShowError(ExceptionCode.GetCodeByExceptionInfo(Detection.rsCode));
            }

            t.Interval = 1000;
            t.Elapsed -= new System.Timers.ElapsedEventHandler(t_Elapsed);
            t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
            t.Start();
            detectionDto = DetectionDto;
            BeginUpload(UploadUrl, DetectionDto.FileGuid, DetectionDto.ActiomId, DetectionDto.FileName);
        }

        void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            OnUpload();

            if (iscomplete)
            {
                isRunning = false;
                t.Elapsed -= new System.Timers.ElapsedEventHandler(t_Elapsed);
                t.Enabled = false;
                //t.Close();
                UploadSuccessDto Successdto = new UploadSuccessDto();
                Successdto.fileGuid = detectionDto.FileGuid;
                Successdto.fileName = detectionDto.FileName;
                Successdto.proj_id = CommonInfo.ProjectId;
                Successdto.taskID = taskID;
                Successdto.taskDocId = taskDocId;
                Successdto.parentFolderId = parentFolderId;
                Successdto.folderId = folderId;
                Successdto.docListId = docListId;
                Successdto.docType = docType;
                Successdto.opType = opType;
                Successdto.userId = CommonInfo.UserGrid;

                string successUrl = BaseClass.GetUrl("Upload", "UploadSuccess");
                BaseDto dto = WebCommunication.JsonRequestServiceToObject<BaseDto>(successUrl, Successdto, CommonInfo.Ticike);
                if (dto.rsCode == "S10000")
                {
                    string sql = "UPDATE DownloadFileLocally set IsSuccess=1 where ActiomId=‘" + detectionDto.ActiomId + "‘";
                    if (SQLiteOperation.UpdataSQlite(sql, null) > 0)
                    {
                        DownloadFileService.UpdateFileListComplete(detectionDto.ActiomId);
                        t.Elapsed -= new System.Timers.ElapsedEventHandler(t_Elapsed);
                        uploadComplete(true, "UploadComplete", detectionDto.FileGuid);
                        return;
                    }
                }
                else
                {
                    string errorinfo=ExceptionCode.GetCodeByExceptionInfo(dto.rsCode);
                    MessageUtil.ShowError(detectionDto.FileName + ":" + errorinfo);
                    string sql = "UPDATE DownloadFileLocally set IsSuccess=2,ErrorInfo=‘" + errorinfo + "‘ where ActiomId=‘" + detectionDto.ActiomId + "‘";
                    SQLiteOperation.UpdataSQlite(sql, null);
                    t.Elapsed -= new System.Timers.ElapsedEventHandler(t_Elapsed);
                    uploadComplete(true, "UploadComplete", detectionDto.FileGuid);
                    return;
                }
            }
            //else {
            //    if(Begin <= End)
            //}
        }
        #endregion

        #region 上传暂停
        /// <summary>
        /// 上传暂停
        /// </summary>
        public void Pause()
        {
            if (this.status != UploadStatus.Uploading)
            {
                MessageUtil.ShowError("只有上传中才能暂停!");
                return;
            }

            // 后台线程会查看状态,如果状态时暂停的,
            // 下载将会被暂停并且状态将随之改为暂停.
            this.status = UploadStatus.Pausing;

            isRunning = false;
        }
        #endregion

        #region 继续上传
        /// <summary>
        /// 继续上传
        /// </summary>
        public void Continue()
        {
            if (this.status != UploadStatus.Pausing)
            {
                MessageUtil.ShowError("只有暂停状态才能继续上传!");
                return;
            }
            this.status = UploadStatus.Uploading;

            isRunning = true;
        }
        #endregion

        #region 取消上传
        ///<summary>
        ///取消上传
        ///</summary>
        public void Cancel(string FileGuid, string Uploadurl, string ActiomId, string FileName)
        {
            this.status = UploadStatus.Cancel;
            cancelTokenSource.Cancel();
            isRunning = false;
            size = DownloadCapacity * 1024;
            End = FileSize;
            UploadMethod(Uploadurl, DownloadCapacity, FileGuid, ActiomId, FileName, size, End,false);

        }
        #endregion

        /// <summary>
        /// 重新上传
        /// </summary>
        public void Again(string UploadUrl, string DetectionUrl, UplpadDetectionFileDto DetectionDto)
        {
            this.status = UploadStatus.Cancel;
            cancelTokenSource.Cancel();
            isRunning = false;
            size = DownloadCapacity * 1024;
            End = FileSize;
            UploadMethod(UploadUrl, DownloadCapacity, DetectionDto.FileGuid, DetectionDto.ActiomId, DetectionDto.FileName, size, End, false);

            status = UploadStatus.Uploading;
            UplpadDetection Detection = WebCommunication.JsonRequestServiceToObject<UplpadDetection>(DetectionUrl, DetectionDto, CommonInfo.Ticike);
            if (Detection.rsCode == "S10000")
            {
                if (Detection.Isexist == true)
                {
                    Begin = Detection.StartingValue;
                }
                else
                {
                    Begin = 0;
                }
            }
            else
            {
                MessageUtil.ShowError(ExceptionCode.GetCodeByExceptionInfo(Detection.rsCode));
            }

            t.Interval = 1000;
            t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
            t.Start();
            detectionDto = DetectionDto;
            BeginUpload(UploadUrl, DetectionDto.FileGuid, DetectionDto.ActiomId, DetectionDto.FileName);
        }

        #region 上传方法
        /// <summary>
        /// 多线程上传
        /// </summary>
        /// <param name="UploadUrl">上传URL</param>
        /// <param name="FileGuid">文件Guid</param>
        private void BeginUpload(string UploadUrl,string FileGuid,string ActiomId,string FileName)
        {
            try
            {
                //获取线程数
                EPMSDto.LocalData.DownloadConfiguration configuration = LocalDataDownloadConfiguration.GetDownloadConfigurationByUserName(CommonInfo.LoginName);
                DownloadCapacity = configuration.DownloadCapacity;
                ////计算出单次下载量
                size = DownloadCapacity * 1024;
                End = FileSize;
                bool complete = false;

                //遍历线程数(遍历几次就是启动几个线程)
                for (int i = 0; i < configuration.ThreadNum; i++)
                {                    //启动任务
                    task = Task.Factory.StartNew(() => UploadMethod(UploadUrl, DownloadCapacity, FileGuid, ActiomId, FileName, size, End, complete), cancelTokenSource.Token);
                    Random rd = new Random();
                    int num= rd.Next(1500,2000);
                    Thread.Sleep(num);
                }

                //UploadMethod(UploadUrl, DownloadCapacity, FileGuid, ActiomId, FileName);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(typeof(DownLoadFile), ex);
            }
        }

        /// <summary>
        /// 上传方法
        /// </summary>
        /// <param name="Uploadurl">上传的路径</param>
        /// <param name="DownloadCapacity">每次上传的大小(用户设置的)</param>
        /// <param name="startingValue"></param>
        public void UploadMethod(string Uploadurl, long DownloadCapacity, string FileGuid, string ActiomId, string FileName, long size, long End, bool complete)
        {
            //if (status != UploadStatus.Uploading)
            //{
            //    return;
            //}
            if (status == UploadStatus.Cancel)
            {
                t.Elapsed -= new System.Timers.ElapsedEventHandler(t_Elapsed);
                string deletesql = "delete from DownloadFileLocally where ActiomId=‘" + ActiomId + "‘";
                if (SQLiteOperation.UpdataSQlite(deletesql, null) == 0)
                {
                    MessageUtil.ShowError("删除上传成功的文件记录出错!");
                }
                DownloadFileService.DeleteFileList(ActiomId);

                WhereDto dt = new WhereDto();
                dt.Where = FileGuid;
                string deleteurl = BaseClass.GetUrl("Upload", "CancelUpload");
                BaseDto dto = WebCommunication.JsonRequestServiceToObject<BaseDto>(deleteurl, dt, CommonInfo.Ticike);

                uploadComplete(true, "UploadCancel", FileGuid);
                return;
            }

            while (End > Begin)
            {
                if (Begin < End)
                {
                    if (!cancelTokenSource.IsCancellationRequested)
                    {
                        //下载保护
                        if (End - Begin < size)
                        {
                            size = End - Begin;
                            if (size < 0)
                            {
                                size = 0;
                            }
                            //上传完成在这里写
                            //iscomplete = true;
                            complete = true;
                        }

                        #region 上传

                        //自旋锁(暂停上传)
                        SpinWait.SpinUntil(() => isRunning);
                        MyUploadFileDto Filedto = new MyUploadFileDto();
                        BeforSecondUploadSize = size;
                        UploadSize = Begin;
                        //文件信息
                        System.IO.FileStream readFs = new System.IO.FileStream(FileUrl, System.IO.FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite);
                        long lenth = readFs.Length;
                        readFs.Position = Begin;
                        byte[] filesize = new byte[size];
                        readFs.Read(filesize, 0, Convert.ToInt32(size));
                        readFs.Close();
                        //MD5加密
                        Filedto.FileMD5 = PasswordEncrypt.getMD5Hash(filesize);
                        Filedto.ByteInfo = filesize;
                        Filedto.StartingValue = Begin;
                        Filedto.Uploadsize = size;
                        Filedto.Guid = FileGuid;

                        BaseDto dto = WebCommunication.JsonRequestServiceToObject<BaseDto>(Uploadurl, Filedto, CommonInfo.Ticike);
                        if (dto.rsCode != "S10000")
                        {
                            MessageUtil.ShowError(ExceptionCode.GetCodeByExceptionInfo(dto.rsCode));
                            return;
                        }
                        iscomplete = complete;
                        #endregion

                    }
                }
                else {
                    iscomplete = complete;
                }
                Begin += size;
            }
            if (End <= Begin)
            {
                iscomplete = true;
            }
        }
        #endregion

        #region 每秒信息事件方法
        /// <summary>
        /// 更新下载所用时间
        /// </summary>
        private void ChangeTime()
        {
            if (this.status == UploadStatus.Uploading)
            {
                DateTime now = DateTime.Now;
                if (now != lastStartTime)
                {
                    useTime = useTime.Add(now - lastStartTime);
                    lastStartTime = now;
                }
            }
        }

        public event UploadEventArgs.SecondUploadEventHandler SecondUploadEvent;
        /// <summary>
        /// 每秒信息方法
        /// </summary>
        public void OnUpload()
        {
            if (SecondUploadEvent != null)
            {
                ChangeTime();
                this.speed = (UploadSize - BeforSecondUploadSize) / 1024;
                long temp = 0;

                this.allTime = new TimeSpan(temp);
                int downLoadProportion = 0;
                if (UploadSize > 0)
                {
                    downLoadProportion = Convert.ToInt32((Convert.ToDecimal(UploadSize) / Convert.ToDecimal(FileSize)) * 100);
                }
                else
                {
                    downLoadProportion = 0;
                }
                UploadEventArgs.SecondUploadEventArgs e = new UploadEventArgs.SecondUploadEventArgs(UploadSize / 1024, useTime, allTime, speed, FileSize / 1024, downLoadProportion);
                SecondUploadEvent(this, e);
            }
        }
        #endregion

        #region 上传完成的事件方法
        public event UploadEventArgs.UploadCompletedEventHandler UploadCompletedEvent;
        /// <summary>
        /// 上传完成的方法
        /// </summary>
        /// <param name="isCompleted"></param>
        /// <param name="state"></param>
        /// <param name="Guid"></param>
        public void uploadComplete(bool isCompleted, string state, string Guid)
        {
            if (UploadCompletedEvent != null)
            {
                UploadEventArgs.UploadCompletedEvent e = new UploadEventArgs.UploadCompletedEvent(isCompleted, state, Guid);
                UploadCompletedEvent(this, e);
            }
        }
        #endregion
    }

文件事件委托定义

#region 委托类
    public class UploadEventArgs
    {
        /// <summary>
        ///  与每秒下载情况相关的委托
        /// </summary>
        /// <param name="sender">事件发起的对象</param>
        /// <param name="e">参数</param>
        public delegate void SecondUploadEventHandler(Object sender, SecondUploadEventArgs e);
        /// <summary>
        /// 下载完成的委托
        /// </summary>
        /// <param name="sender">事件发起的对象</param>
        /// <param name="e">参数</param>
        public delegate void UploadCompletedEventHandler(Object sender, UploadCompletedEvent e);

        /// <summary>
        /// 下载时每秒事件相关的参数
        /// </summary>
        public class SecondUploadEventArgs : EventArgs
        {
            /// <summary>
            /// 已下载大小
            /// </summary>
            public readonly long uploadSize;

            /// <summary>
            /// 下载已耗时
            /// </summary>
            public readonly TimeSpan useTime;

            //预计下载总耗时
            public readonly TimeSpan allTime;

            /// <summary>
            /// 当前下载速度
            /// </summary>
            public readonly double speed;

            /// <summary>
            /// 文件总大小
            /// </summary>
            public readonly long fileSize;
            /// <summary>
            /// 上传比例
            /// </summary>
            public readonly int uploadProportion;

            public SecondUploadEventArgs(long uploadSize, TimeSpan useTime, TimeSpan allTime, double speed, long fileSize, int uploadproportion)
            {
                this.uploadSize = uploadSize;
                this.useTime = useTime;
                this.allTime = allTime;
                this.speed = speed;
                this.fileSize = fileSize;
                uploadProportion = uploadproportion;
            }
        }

        /// <summary>
        /// 上传完成的
        /// </summary>
        public class UploadCompletedEvent : EventArgs
        {
            /// <summary>
            /// 是否完成
            /// </summary>
            public readonly bool UploadComplete;
            /// <summary>
            /// 上传状态
            /// </summary>
            public readonly string UploadState;

            public readonly string FileGuid;
            public UploadCompletedEvent(bool isComplete, string state, string Guid)
            {
                UploadComplete = isComplete;
                UploadState = state;
                FileGuid = Guid;
            }
        }

    }
    #endregion

    #region 上传状态枚举
    public enum UploadStatus
    {
        /// <summary>
        /// 下载
        /// </summary>
        Uploading,
        /// <summary>
        ///
        /// </summary>
        Pausing,
        /// <summary>
        /// 空线
        /// </summary>
        Idle,
        /// <summary>
        /// 取消
        /// </summary>
        Cancel,
        /// <summary>
        /// 重新下载
        /// </summary>
        ReDownload,
        /// <summary>
        /// 完成下载
        /// </summary>
        Complete
    }
    #endregion

WebAPI获取文件,保存文件

/// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="fileDto"></param>
        /// <returns></returns>
        public static BaseDto UploadFile(MyUploadFileDto fileDto)
        {
            BaseDto dto = new BaseDto();
            //获取到的文件转为MD5码
            string md5code=PasswordEncrypt.getMD5Hash(fileDto.ByteInfo);
            //判断文件转成的MD5码是否与传递来的MD5码一直,不一致则返回异常码信息
            if (md5code != fileDto.FileMD5) {
                dto.rsCode = ErrorExceptionCode.ExceptionCode.UploadFile_MD5Error;
                return dto;
            }
            //获取默认路径
            string Path = System.IO.Path.Combine(FileDownloadHandler.GetWebConfigureDocumentPath("DocumentLocation"));
            //判断默认路径是否存在,不存在则新建
            if (!Directory.Exists(Path))
            {
                Directory.CreateDirectory(Path);
            }
            //组成保存文件的路径
            string address = System.IO.Path.Combine(Path, fileDto.Guid);
            //string address = @"E:\\upload\\" + fileDto.FileName;
            try
            {
                //写入文件
                using (FileStream _fs = new FileStream(address, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
                {
                    //文件写入起始位置
                    _fs.Position = fileDto.StartingValue;
                    _fs.Write(fileDto.ByteInfo, 0, (int)fileDto.Uploadsize);
                    _fs.Flush();
                    _fs.Close();
                    _fs.Dispose();
                }
                dto.rsCode = ErrorExceptionCode.ExceptionCode.Success;
            }
            catch (Exception)
            {
                dto.rsCode = ErrorExceptionCode.ExceptionCode.UploadFile_FileSaveError;
            }
            return dto;
        }

调用上传文件公共类

UplpadDetectionFileDto fileDto=new UplpadDetectionFileDto();
            fileDto.FileName=UploadName;
            fileDto.FileGuid = FileGuid;
            fileDto.ActiomId = ActiomId;
            //实例化上传
            //UploadFile file = new UploadFile();
            file.docListId = docListId;
            file.docType = docType;
            file.folderId = folderId;
            file.opType = opType;
            file.parentFolderId = parentFolderId;
            file.taskDocId = taskDocId;
            file.taskID = taskID;
            file.FileSize = FileSize;
            file.FileUrl = FileUrl;
            //每一秒上传情况信息时间
            file.SecondUploadEvent += new UploadEventArgs.SecondUploadEventHandler(file_SecondUploadEvent);
            //上传完成的事件
            file.UploadCompletedEvent += new UploadEventArgs.UploadCompletedEventHandler(file_UploadCompletedEvent);
            //启动上传
            file.Startup(UploadUrl, DetectionUrl, fileDto);

时间: 2024-10-12 08:08:29

多线程文件分片上传的相关文章

iOS大文件分片上传和断点续传

总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件切片(分块),但这不是我们现在说的重点,我们要做的事是保证在网络中断后1G的文件已上传的那部分在下次网络连接时不必再重传.所以我们本地在上传的时候,要将大文件进行分片,比如分成1024*1024B,即将大文件分成1M的片进行上传,服务器在接收后,再将这些片合并成原始文件,这就是分片的基本原理.断点续

plupload 大文件分片上传与PHP分片合并探索

最近老大分给我了做一个电影cms系统,其中涉及到一个功能,使用七牛云的文件上传功能.七牛javascript skd,使用起来很方便,屏蔽了许多的技术细节.如果只满足与调用sdk,那么可能工作中也就没有什么收获了.其中对七牛云的服务很佩服的一点是,无论我上传多大的文件,当我文件最后一片上传完成的时候,就立刻返回到文件链接,这个问题我想了好久,也不知道七牛是如何做到的. 七牛云的sdk分为 JavaScript 与 PHP端. JavaScript端的作用是提供文件上传功能,客户端(浏览器)无需关

网页 大文件分片上传处理

总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件切片(分块),但这不是我们现在说的重点,我们要做的事是保证在网络中断后1G的文件已上传的那部分在下次网络连接时不必再重传.所以我们本地在上传的时候,要将大文件进行分片,比如分成1024*1024B,即将大文件分成1M的片进行上传,服务器在接收后,再将这些片合并成原始文件,这就是分片的基本原理.断点续

大文件分片上传,断点续传,秒传 实现

前段时间做视频上传业务,通过网页上传视频到服务器. 视频大小 小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题:1,文件过大,超出服务端的请求大小限制:2,请求时间过长,请求超时:3,传输中断,必须重新上传导致前功尽弃: 解决方案: 1,修改服务端上传的限制配置:Nginx 以及 PHP 的上传文件限制 不宜过大,一般5M 左右为好: 2,大文件分片,一片一片的传到服务端,再由服务端合并.这么做的好处在于一旦上传失败只是损失一个分片而已,不用整个文件重传,而且每个分

大文件分片上传

Vue项目中遇到了大文件分片上传的问题,之前用过webuploader,索性就把Vue2.0与webuploader结合起来使用,封装了一个vue的上传组件,使用起来也比较舒爽. 上传就上传吧,为什么搞得那么麻烦,用分片上传? 分片与并发结合,将一个大文件分割成多块,并发上传,极大地提高大文件的上传速度.当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件.另外分片传输能够更加实时的跟踪上传进度. 实现后的界面: 主要是两个文件,封装的上传组件和具体的ui页面,上传组件代码下面有列出来.

js实现大文件分片上传的方法

借助js的Blob对象FormData对象可以实现大文件分片上传的功能,关于Blob和FormData的具体使用方法可以到如下地址去查看FormData 对象的使用Blob 对象的使用以下是实现代码,本例中后端代码使用php来实现,只是演示基本功能,具体一些文件验证逻辑先忽略.前段代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <

js+php大文件分片上传

1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通过浏览器上传至服务器,做一层中转便可以实现,但当这份文件非常大到了10GB级别,我们就需要思考另一种形式的技术方案了,也就是本文要阐述的方案. 技术要求主要有以下几方面: 支持超大数据量.10G级别以上 稳定性:除网络异常情况100%成功 准确性:数据无丢失,读写准确性100% 效率:1G文件分钟级

PHP大文件分片上传

一.前言 在网站开发中,经常会有上传文件的需求,有的文件size太大直接上传,经常会导致上传过程中耗时太久,大量占用带宽资源,因此有了分片上传. 分片上传主要是前端将一个较大的文件分成等分的几片,标识当前分片是第几片和总共几片,待所有的分片均上传成功的时候,在后台进行合成文件即可. 二.开发过程中遇到的问题 分片的时候每片该分多大size?太大会出现"413 request entity too large" 分片上传的时候并不是严格按照分片的序号顺序上传,如何判断所有的分片均上传成功

springboot2.0结合webuploader实现文件分片上传

目录 1. 上传页面代码 2. nginx配置 3. 后台主要代码 3.1 application.yml 3.2 跨域处理 3.3 控制器代码 3.4 service代码 4. 执行测试 1. 上传页面代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>webuploader文件上传</title>