dotnetzip 创建空的损坏文件

Posted

技术标签:

【中文标题】dotnetzip 创建空的损坏文件【英文标题】:dotnetzip creating empty corrupted file 【发布时间】:2019-05-01 19:11:20 【问题描述】:

我正在尝试创建一个 HTTP 触发函数,该函数将从 Azure 存储中提取一个 blob,对其进行压缩,然后将 zip 重新上传到 blob 存储。在此过程中的某个地方出现了问题。它成功压缩并重新上传,但压缩文件的内容为 0KB,无法打开。任何帮助,将不胜感激。在下面找到代码。

 public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
    
        log.Info("C# HTTP trigger function processed a request.");
        try
        
          string fileName = req.GetQueryNameValuePairs()
                .FirstOrDefault(q => string.Compare(q.Key, "fileName", true) == 0)
                .Value;

            log.Info($"fileName: fileName");

            dynamic request = await req.Content.ReadAsAsync<object>();
            var container = (string)request.body;

            string connectionString = Environment.GetEnvironmentVariable("blobstorageconnectionstring");
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
            CloudBlobClient client = storageAccount.CreateCloudBlobClient();

            MemoryStream outputStream = new MemoryStream();

            using (ZipFile zip = new ZipFile())
            
                zip.AddEntry($"fileName.xlsx", DownloadFromBlobStorage(fileName, connectionString, container));
                zip.CompressionMethod = CompressionMethod.Deflate;
                zip.Save(outputStream);
            


            UploadToBlobStorage(fileName + "ZIP", outputStream, connectionString, container);

            return req.CreateResponse(HttpStatusCode.OK, "OK");
        
        catch (Exception ex)
        
            log.Error("error", ex: ex);

            return req.CreateResponse(HttpStatusCode.BadRequest);
        

    
    private static void UploadToBlobStorage(string name, MemoryStream dataStream, string storageConnectionString, string blobContainerName)
    

        CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);
        CloudBlobClient client = account.CreateCloudBlobClient();

        CloudBlobContainer container = client.GetContainerReference(blobContainerName);
        container.CreateIfNotExists();

        CloudBlockBlob blob = container.GetBlockBlobReference(name);
        blob.Properties.ContentType = "application/x-zip-compressed";

        dataStream.Position = 0;
        blob.UploadFromStream(dataStream);
    
    private static MemoryStream DownloadFromBlobStorage(string fileName, string storageConnectionString, string blobContainerName)
    

        CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);
        CloudBlobClient client = account.CreateCloudBlobClient();

        CloudBlobContainer container = client.GetContainerReference(blobContainerName);
        container.CreateIfNotExists();

        CloudBlockBlob blob = container.GetBlockBlobReference(fileName);

        MemoryStream memStream = new MemoryStream();

        blob.DownloadToStream(memStream);

        return memStream;
    

【问题讨论】:

【参考方案1】:

您似乎也应该将从DownloadFromBlobStorage() 返回的MemoryStream 对象定位为零(您已经在UploadToBlobStorage() 上使用outputStream/dataStream 执行此操作),然后将其传递给zip.AddEntry()

   MemoryStream inputStream = DownloadFromBlobStorage(fileName, connectionString, container);
   inputStream.Position = 0;
   zip.AddEntry($"fileName.xlsx", inputStream);

看看这个答案:

Creating Zip file from stream and downloading it - Stack Overflow

经过更多研究,我发现通常您应该始终在将流传递给函数之前定位它:

Who is responsible for stream positioning? - Software Engineering Stack Exchange

【讨论】:

修复了它。我觉得很笨。谢谢!! 作为替代方案:inputStream.Seek(0, SeekOrigin.Begin); @JohnyL,是的,这就是我链接的答案中使用它的方式,所以我研究了差异,但在这种情况下,两种方法之间没有区别:Stream.Seek(0, SeekOrigin.Begin) or Position = 0

以上是关于dotnetzip 创建空的损坏文件的主要内容,如果未能解决你的问题,请参考以下文章

防止 DotNetZip 创建额外的文件夹

ZipArchive php 获取损坏或空的 zip

将命令行参数传递给使用 DotNetZip 创建的 SFX

HSSF生成excel文件损坏

使用 DotNetZip 仅从 zip 中提取 XML 文件

使用 DotNetZip 打开拆分 Zip 文件