コード例 #1
0
        private async Task CompressZip(ZipArchive zip, MyCompressFile compressFile, CancellationToken token = default)
        {
            foreach (var internalFilePair in compressFile.InternalFiles)
            {
                var entryKey     = internalFilePair.Key;
                var internalFile = internalFilePair.Value;
                if (internalFile.IsPackage)
                {
                    //如果是压缩包,获取有效的Key
                    entryKey = GetValidEntryKey(compressFile, entryKey);

                    var tmpFile = Path.GetTempFileName();
                    using (var childZip = ZipFile.Open(tmpFile, ZipArchiveMode.Update))
                    {
                        await CompressZip(childZip, internalFile, token);
                    }
                    internalFile.TempFilePath = tmpFile;
                }
                var entry = zip.CreateEntry(entryKey);
                using (var stream = internalFile.IsPackage //如果是压缩包,则读取文件;否则直接读取下载的文件流
                    ? File.OpenRead(internalFile.TempFilePath)
                    : await _fastDfsHttpClient.DownloadAsync(internalFile.FileUrl, token))
                {
                    using (var entryStream = entry.Open())
                    {
                        await stream.CopyToAsync(entryStream);
                    }
                }
                //子压缩包数据已经写入父压缩包后,删除子压缩包文件
                if (internalFile.IsPackage)
                {
                    File.Delete(internalFile.TempFilePath);
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// 读取压缩包、文件夹、嵌套压缩包的路径层级结构,返回根压缩包文件信息
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        private static MyCompressFile ReadPathLevel(Dictionary <string, string> dic)
        {
            var rootPackage = new MyCompressFile("root.zip", true);

            foreach (var keyPair in dic)
            {
                var parentPackage = rootPackage;
                //去掉开始的斜杠,否则会多一级空目录
                var arrPath = keyPair.Key.Split(CompressIdentifier).Select(o => o.TrimStart('/', '\\')).ToArray();
                //前面为上级嵌套压缩包路径,最后一份为文件相对上级压缩包的路径
                var fileRelativePath = arrPath[arrPath.Length - 1];
                for (int i = 0; i < arrPath.Length - 1; i++)
                {
                    var packageRelativePath = arrPath[i];
                    if (!parentPackage.InternalFiles.TryGetValue(packageRelativePath, out var subPackage))
                    {
                        subPackage = new MyCompressFile(packageRelativePath, true);
                        parentPackage.InternalFiles.Add(packageRelativePath, subPackage);
                    }

                    parentPackage = subPackage;
                }
                var file = new MyCompressFile(fileRelativePath)
                {
                    FileUrl = keyPair.Value
                };

                parentPackage.InternalFiles.Add(fileRelativePath, file);
            }
            //如果根压缩包下仅有一个文件且为压缩包,则去掉最外层根压缩包壳
            if (rootPackage.InternalFiles.Count == 1 && rootPackage.InternalFiles.First().Value.IsPackage)
            {
                rootPackage = rootPackage.InternalFiles.First().Value;
            }

            return(rootPackage);
        }
コード例 #3
0
        private static string GetValidEntryKey(MyCompressFile compressFile, string entryKey)
        {
            if (entryKey.EndsWith(ZipExt, StringComparison.InvariantCultureIgnoreCase) &&
                entryKey.Length > ZipExt.Length)    //防止 entryKey 就是.zip的情况
            {
                return(entryKey);
            }
            //如果是压缩包,且不是zip结尾,则在后缀添加.zip(不能直接改后缀,存在同名的rar、7z、zip压缩包或文件夹)
            var renameKey = entryKey + ZipExt;
            //添加.zip后,如果存在同名,需要区分(极端情况处理,及其少见)
            //abc.rar文件  abc.7z文件  abc.zip文件  abc.rar.zip文件夹  abc.7z.zip文件 (同级目录存在这5个文件时的类似极端情况)
            //不仅需要判断同层级文件名相同,还需要判断同层次是否存在同名文件夹
            int i = 0;

            while (compressFile.InternalFiles.ContainsKey(renameKey) ||
                   compressFile.InternalFiles.Keys.Any(key => key.StartsWith($"{renameKey}/") || //判断同层次文件夹是否相同
                                                       key.StartsWith($"{renameKey}\\")))
            {
                i        += 1;
                renameKey = $"{entryKey}重名区分({i}){ZipExt}";
            }

            return(renameKey);
        }