public void VirDownload(List <E_SourceFile> sourceList)
 {
     fileList = sourceList;
     //文件个数以及大小校验
     if (fileList.Count == 0)
     {
         ExitError("文件不存在"); return;
     }
     if (fileList.Sum(s => (long)s.FileSize) > int.MaxValue)
     {
         ExitError("文件过大,请减少文件个数后下载"); return;
     }
     try
     {
         ProcessSoftList();
         //根据资料集合构建
         E_VirtualZipStruct zipStruct = BuildZipStruct();
         //发送文件
         SendFile(zipStruct);
     }
     catch (OutOfMemoryException)
     {
         float a = GetFreeMemory(0);
         Util.SaveLog(_config.LogPath, $"当前内存不足,剩余内存为:{GetFreeMemory()}MB(排除了保留内存{_config.ReseverMemory / 1024 / 1024}GB)");
         ExitError("服务器忙...请稍后再试"); return;
     }
     catch (Exception ex)
     {
         Util.SaveLog(_config.LogPath, ex.StackTrace.ToString());
         ExitError("服务器异常,请稍后重试"); return;
     }
 }
        /// <summary>
        /// 发送文件
        /// </summary>
        /// <param name="zipStruct">Zip结构</param>
        private void SendFile(E_VirtualZipStruct zipStruct)
        {
            //设定默认字节流
            uint DefaultBuffer = 256 * 1024;
            //已经读取的文件流长度
            uint readOffset = 0;
            //缓冲区位移,用于判断是否该写入
            uint   bfrOffset    = 0;
            string saveFileName = string.Format("打包下载{0}等{1}个文件.zip", fileList[0].FileName, fileList.Count);

            context.Response.ContentType = "application/octet-stream";
            context.Response.AddHeader("Content-Disposition", "attachement;filename=" + HttpUtility.UrlEncode(saveFileName));
            context.Response.AddHeader("Content-Length", zipStruct.ZipFileSize.ToString());
            context.Response.AddHeader("Connection", "Keep-Alive");
            //重置写入文件的Buffer大小(用于重置小于1M的文件大小)
            byte[] bfrByte = ResetBuffer(ref readOffset, zipStruct.ZipFileSize, DefaultBuffer);
            #region 文件读取
            //1.读取zipXml中的data区域
            foreach (var item in zipStruct.Header)
            {
                //1-1.读取头部区域的头部字节部分
                {
                    //读取配置中的头部字节
                    byte[] headerByte = item.Item1;
                    //定义头部字节读取时的偏移量
                    ReadAndWrite(zipStruct.ZipFileSize, DefaultBuffer, ref readOffset, ref bfrOffset, ref bfrByte, headerByte);
                }
                //1-2.读取头部区域的文件流
                {
                    string path = item.Item2;
                    ReadAndWrite(zipStruct.ZipFileSize, DefaultBuffer, ref readOffset, ref bfrOffset, ref bfrByte, path);
                }
            }
            //2.读取zipXML中的DIR区域
            {
                byte[] DirByte = zipStruct.Dir.ToArray();
                ReadAndWrite(zipStruct.ZipFileSize, DefaultBuffer, ref readOffset, ref bfrOffset, ref bfrByte, DirByte);
            }
            //3.读取zipXML中的End区域
            {
                byte[] EndByte = zipStruct.End.ToArray();
                ReadAndWrite(zipStruct.ZipFileSize, DefaultBuffer, ref readOffset, ref bfrOffset, ref bfrByte, EndByte);
            }

            context.Response.Close();
            context.Response.End();
            #endregion
        }
        /// <summary>
        /// 构建Zip结构
        /// </summary>
        /// <returns></returns>
        private E_VirtualZipStruct BuildZipStruct()
        {
            E_VirtualZipStruct zipStruct = new E_VirtualZipStruct();
            //定义头部和目录的集合(用于计算目录偏移量)
            List <E_FileAndDir> fdList = new List <E_FileAndDir>();
            //合计文件大小
            long totalFileSize = 0;
            //虚拟压缩包总大小(包含文件大小和头部,目录,尾部区域的字节)
            long virtualZipSize = 0;

            foreach (var file in fileList)
            {
                //1.构造头部区域
                E_LocalFileHeader header = FileHeaderInstance(file);
                zipStruct.Header.Add(new Tuple <byte[], string>(header.GetAllBytes(), file.PhyFilePath));
                virtualZipSize += header.GetAllBytes().Count();
                //2.构造目录部分
                E_CentralDirFileHeader dir = CentralDirInstance(file);
                //计算dir的偏移量
                if (fdList.Count > 0)
                {
                    dir.HeaderOffset = GetClassSize(fdList.Select(s => s.Header).ToList(), (int)totalFileSize);
                }
                zipStruct.Dir.AddRange(dir.GetAllBytes());
                //向头部和目录集合添加记录
                fdList.Add(new E_FileAndDir()
                {
                    Header = header,
                    Dir    = dir
                });
                totalFileSize += file.FileSize;
            }
            E_EndCentralDirRecord endDir = EndDirInstance(fdList, (int)totalFileSize);

            zipStruct.End.AddRange(endDir.GetAllBytes());
            virtualZipSize       += zipStruct.Dir.Count();
            virtualZipSize       += zipStruct.End.Count();
            virtualZipSize       += totalFileSize;
            zipStruct.ZipFileSize = (uint)virtualZipSize;
            return(zipStruct);
        }
Пример #4
0
        public void VirDownload(IList <E_SourceFile> sourceList)
        {
            fileList = sourceList;

            //文件个数以及大小校验
            if (fileList.Count == 0)
            {
                ExitError("文件不存在"); return;
            }
            if (fileList.Sum(s => (long)s.FileSize) > int.MaxValue)
            {
                ExitError("文件过大,请减少文件个数后下载"); return;
            }
            //处理资料文件地址,文件名等
            try
            {
                ProcessSoftList();
            }
            catch (OutOfMemoryException)
            {
                float a = GetFreeMemory(0);
                ExitError("服务器忙...请稍后再试"); return;
            }
            catch (Exception ex)
            {
                try
                {
                    Util.SaveLog(_config.ErrorLogSavePath, ex.StackTrace.ToString());
                }
                catch { }
                ExitError("服务器异常,请稍后重试"); return;
            }
            //根据资料集合构建
            E_VirtualZipStruct zipStruct = BuildZipStruct();

            //发送文件
            SendFile(zipStruct);
        }