この記事はネチズンが投稿した。
著者:江湖の人々
前の記事:2022年末にC#zipファイルを解凍するバグが発生
原文へのリンク:https//jhrs.com/2022/46060.html
最近、アップロード機能のトラブルシューティングでは、クライアントはzipファイルをアップロードし、C#zipファイルを解凍するコードを使用してサーバー側にzipファイルをアップロードし、アップロードが許可されているファイルタイプであるかどうかを確認し、ファイルサフィックスを変更することを確認する必要があり、ファイルヘッダーは何でも行く必要があります。
C#zipファイルを解凍
先说一下前文(或者上下文),在 IIS 上部署了一个文件服务站点,用于上传各类文件,流程上是先上传到站点根目录里面随机创建的一个临时目录(这里采用偷懒方案,直接使用 guid 作为目录名创建),先通过文件验证后再将其通过代码剪切或者复制到正式存档目录,C# 复制或者移动文件的代码可以参考江湖人士网的这篇文章。昨天快下班时发现上传 zip 文件时报错,在文件服务根站点创建了很多很多的 guid 开头的目录,我的妹呀,这下玩犊子了,事出反常必有妖啊,肯定代码出错了。

バグのある解凍コード。
これはすぐに2022年末になります。このバグが発生した後、シミュレーション環境を構築して実行すると、次の元のコードに問題があることがわかりました。
/// <summary>
/// 解压文件
/// </summary>
/// <param name="saveDir">保存目录</param>
/// <param name="stream"></param>
public static void UnZipFiles(string saveDir, Stream stream)
{
using (ZipInputStream s = new ZipInputStream(stream))
{
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
string directoryName = $"{saveDir}{Path.GetDirectoryName(theEntry.Name)}\\";
string fileName = Path.GetFileName(theEntry.Name);
Directory.CreateDirectory(directoryName);
using (FileStream streamWriter = File.Create(directoryName + fileName))
{
byte[] data = new byte[2048];
while (true)
{
int size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
}
}
}
}
对了,这里需要说明一下,这是以前的老项目,因此压缩,解压使用了 ICSharpCode.SharpZipLib.Zip 这个组件。
オープンソースを見ると、一目で問題が見つかり、論理が厳密ではなく、解凍ファイル保存ディレクトリが直接スプライシングにつながります。
このバグを修正する方法は?
知道了问题所在,修复自然简单,调用Path.Combine方法即可,解压时再判断一下是目录还是文件即可,最终修复后的代码如下:
/// <summary>
/// 解压文件
/// </summary>
/// <param name="saveDir">保存目录</param>
/// <param name="stream"></param>
public static void UnZipFiles(string saveDir, Stream stream)
{
using (ZipInputStream s = new ZipInputStream(stream))
{
ZipEntry theEntry;
string directoryName, file, fileName;
while ((theEntry = s.GetNextEntry()) != null)
{
directoryName = Path.Combine(saveDir, Path.GetDirectoryName(theEntry.Name));
fileName = Path.GetFileName(theEntry.Name);
Directory.CreateDirectory(directoryName);
file = Path.Combine(directoryName, fileName);
if (theEntry.IsFile)
{
using (FileStream streamWriter = File.Create(file))
{
byte[] data = new byte[2048];
while (true)
{
int size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
}
}
}
}
}