C# 无法使用Ionic.zip创建zip文件

C# 无法使用Ionic.zip创建zip文件,c#,zipfile,dotnetzip,C#,Zipfile,Dotnetzip,我不确定我在哪里做错了什么,但我正在使用DotNetZip库创建的zip正在创建一个内容为空的zip文件。或者zip中的文件大小显示为0Kb,无法打开 代码: 公共静态异步任务DotNetZipFileAsync(MemoryStream流、字符串桶、列表PdfileSet、IAmazonS3 s3Client) { 使用Ionic.Zip.ZipFile Zip=new ZipFile(); foreach(PdfileSet中的var Pdfile) { foreach(pdfFile中的v

我不确定我在哪里做错了什么,但我正在使用DotNetZip库创建的zip正在创建一个内容为空的zip文件。或者zip中的文件大小显示为0Kb,无法打开

代码:

公共静态异步任务DotNetZipFileAsync(MemoryStream流、字符串桶、列表PdfileSet、IAmazonS3 s3Client)
{
使用Ionic.Zip.ZipFile Zip=new ZipFile();
foreach(PdfileSet中的var Pdfile)
{
foreach(pdfFile中的var文件)
{
GetObjectRequest=新的GetObjectRequest
{
BucketName=bucket,
密钥=文件
};
使用GetObjectResponse=wait s3Client.GetObjectAsync(请求);
使用Stream responseStream=response.responseStream;
ZipEntry-ZipEntry=zip.AddEntry(file.Split('/')[^1],responseStream);
等待响应stream.CopyToAsync(流);
}
}
压缩保存(流);
stream.Seek(0,SeekOrigin.Begin);
等待stream.CopyToAsync(新文件流(@“C:\LocalRepo\Temp.zip”、FileMode.OpenOrCreate、FileAccess.ReadWrite、FileShare.ReadWrite));
}
}
}

您的代码至少有两个问题:

  • 读取流被
    等待响应stream.CopyToAsync(流)
    完全消耗。您可以倒带responseStream来处理这个问题,但是将数据保存到内存流中是完全无用的

  • 响应流在调用
    zip.Save
    之前被释放

  • 您可以做的是:在调用Save之前保持流的打开状态,然后再进行处理。正如Alexey Rumyantsev所发现的(参见注释),在保存ZIP文件之前,还需要保留
    GetObjectResponse
    对象

    using Ionic.Zip.ZipFile zip = new ZipFile();
    var disposables = List<IDisposable>();
    try
    {
        foreach (var pdfFile in pdfFileSet)
        {
            foreach (var file in pdfFile)
            {
                GetObjectRequest request = new GetObjectRequest
                {
                    BucketName = bucket,
                    Key = file
                };
                
                var response = await s3Client.GetObjectAsync(request);
                disposables.Add(response);
                var responseStream = response.ResponseStream;
                disposables.Add(responseStream);
                ZipEntry zipEntry = zip.AddEntry(file.Split('/')[^1], responseStream);
            }
        }
        using var fileStream = new FileStream(@"C:\LocalRepo\Temp.zip", FileMode.Create, FileAccess.Write);        
        zip.Save(fileStream);
    }
    finally
    {
        foreach (var disposable in disposables)
        {
            disposable.Dispose();
        }
    }
    
    使用Ionic.Zip.ZipFile Zip=new ZipFile();
    var disposables=List();
    尝试
    {
    foreach(PdfileSet中的var Pdfile)
    {
    foreach(pdfFile中的var文件)
    {
    GetObjectRequest=新的GetObjectRequest
    {
    BucketName=bucket,
    密钥=文件
    };
    var response=wait s3Client.GetObjectAsync(请求);
    一次性使用。添加(响应);
    var responseStream=response.responseStream;
    一次性用品。添加(responseStream);
    ZipEntry-ZipEntry=zip.AddEntry(file.Split('/')[^1],responseStream);
    }
    }
    使用var fileStream=newfilestream(@“C:\LocalRepo\Temp.zip”,FileMode.Create,FileAccess.Write);
    保存(文件流);
    }
    最后
    {
    foreach(一次性使用的var)
    {
    一次性的,一次性的;
    }
    }
    

    有一些关于如何使其更智能的提示。

    您的代码至少有两个问题:

    public static async Task DotNetZipFileAsync(string bucket, List<List<string>> pdfFileSet, IAmazonS3 s3Client)
    {
        int read;
        using Ionic.Zip.ZipFile zip = new ZipFile();
        byte[] buffer = new byte[16 * 1024];
        
        foreach (var pdfFile in pdfFileSet)
        {
            foreach (var file in pdfFile)
            {
                GetObjectRequest request = new GetObjectRequest
                {
                    BucketName = bucket,
                    Key = file
                };
    
                using GetObjectResponse response = await s3Client.GetObjectAsync(request);
                using Stream responseStream = response.ResponseStream;
                using (MemoryStream ms = new MemoryStream())
                {
                    while ((read = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        ms.Write(buffer, 0, read);
                    }
                    zip.AddEntry(file.Split('/')[^1], ms.ToArray());
                }
            }
        }
        using var fileStream = new FileStream(@"C:\LocalRepo\Temp.zip", FileMode.Create, FileAccess.Write);
        zip.Save(fileStream);
    }
    
  • 读取流被
    等待响应stream.CopyToAsync(流)
    完全消耗。您可以倒带responseStream来处理这个问题,但是将数据保存到内存流中是完全无用的

  • 响应流在调用
    zip.Save
    之前被释放

  • 您可以做的是:在调用Save之前保持流的打开状态,然后再进行处理。正如Alexey Rumyantsev所发现的(参见注释),在保存ZIP文件之前,还需要保留
    GetObjectResponse
    对象

    using Ionic.Zip.ZipFile zip = new ZipFile();
    var disposables = List<IDisposable>();
    try
    {
        foreach (var pdfFile in pdfFileSet)
        {
            foreach (var file in pdfFile)
            {
                GetObjectRequest request = new GetObjectRequest
                {
                    BucketName = bucket,
                    Key = file
                };
                
                var response = await s3Client.GetObjectAsync(request);
                disposables.Add(response);
                var responseStream = response.ResponseStream;
                disposables.Add(responseStream);
                ZipEntry zipEntry = zip.AddEntry(file.Split('/')[^1], responseStream);
            }
        }
        using var fileStream = new FileStream(@"C:\LocalRepo\Temp.zip", FileMode.Create, FileAccess.Write);        
        zip.Save(fileStream);
    }
    finally
    {
        foreach (var disposable in disposables)
        {
            disposable.Dispose();
        }
    }
    
    使用Ionic.Zip.ZipFile Zip=new ZipFile();
    var disposables=List();
    尝试
    {
    foreach(PdfileSet中的var Pdfile)
    {
    foreach(pdfFile中的var文件)
    {
    GetObjectRequest=新的GetObjectRequest
    {
    BucketName=bucket,
    密钥=文件
    };
    var response=wait s3Client.GetObjectAsync(请求);
    一次性使用。添加(响应);
    var responseStream=response.responseStream;
    一次性用品。添加(responseStream);
    ZipEntry-ZipEntry=zip.AddEntry(file.Split('/')[^1],responseStream);
    }
    }
    使用var fileStream=newfilestream(@“C:\LocalRepo\Temp.zip”,FileMode.Create,FileAccess.Write);
    保存(文件流);
    }
    最后
    {
    foreach(一次性使用的var)
    {
    一次性的,一次性的;
    }
    }
    
    对于如何使其更智能,有一些提示。

    公共静态异步任务DotNetZipFileAsync(字符串bucket、列表pdfFileSet、IAmazonS3 s3Client)
    
    public static async Task DotNetZipFileAsync(string bucket, List<List<string>> pdfFileSet, IAmazonS3 s3Client)
    {
        int read;
        using Ionic.Zip.ZipFile zip = new ZipFile();
        byte[] buffer = new byte[16 * 1024];
        
        foreach (var pdfFile in pdfFileSet)
        {
            foreach (var file in pdfFile)
            {
                GetObjectRequest request = new GetObjectRequest
                {
                    BucketName = bucket,
                    Key = file
                };
    
                using GetObjectResponse response = await s3Client.GetObjectAsync(request);
                using Stream responseStream = response.ResponseStream;
                using (MemoryStream ms = new MemoryStream())
                {
                    while ((read = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        ms.Write(buffer, 0, read);
                    }
                    zip.AddEntry(file.Split('/')[^1], ms.ToArray());
                }
            }
        }
        using var fileStream = new FileStream(@"C:\LocalRepo\Temp.zip", FileMode.Create, FileAccess.Write);
        zip.Save(fileStream);
    }
    
    { int-read; 使用Ionic.Zip.ZipFile Zip=new ZipFile(); 字节[]缓冲区=新字节[16*1024]; foreach(PdfileSet中的var Pdfile) { foreach(pdfFile中的var文件) { GetObjectRequest=新的GetObjectRequest { BucketName=bucket, 密钥=文件 }; 使用GetObjectResponse=wait s3Client.GetObjectAsync(请求); 使用Stream responseStream=response.responseStream; 使用(MemoryStream ms=new MemoryStream()) { 而((read=responseStream.read(buffer,0,buffer.Length))>0) { ms.Write(缓冲区,0,读取); } zip.AddEntry(file.Split('/')[^1],ms.ToArray()); } } } 使用var fileStream=newfilestream(@“C:\LocalRepo\Temp.zip”,FileMode.Create,FileAccess.Write); 保存(文件流); }
    公共静态异步任务DotNetZipFileAsync(字符串存储桶、列表pdfFileSet、IAmazonS3 s3Client)
    {
    int-read;
    使用Ionic.Zip.ZipFile Zip=new ZipFile();
    字节[]缓冲区=新字节[16*1024];
    foreach(PdfileSet中的var Pdfile)
    {
    foreach(pdfFile中的var文件)
    {
    GetObjectRequest=新Ge