0

I am using the following code to upload an XML file to an Azure Blob Storage account using the DotNetZip nuget package.

            XmlDocument doc = new XmlDocument();
            doc.Load(path);
            string xmlContent = doc.InnerXml;
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
            var cloudBlobClient = storageAccount.CreateCloudBlobClient();
            var cloudBlobContainer = cloudBlobClient.GetContainerReference(container);
            cloudBlobContainer.CreateIfNotExists();
            using (var fs = File.Create("test.zip"))
            {
                using (var s = new ZipOutputStream(fs))
                {
                    s.PutNextEntry("entry1.xml");
                    byte[] buffer = Encoding.ASCII.GetBytes(xmlContent);
                    s.Write(buffer, 0, buffer.Length);
                    fs.Position = 0;      
                    //Get the blob ref
                    var blob = cloudBlobContainer.GetBlockBlobReference("test.zip");          
                    blob.Properties.ContentEncoding = "zip"
                    blob.Properties.ContentType = "text/plain";
                    blob.Metadata["filename"] = "test.zip";
                    blob.UploadFromStream(fs);
                }
            }

This code creates a zip file in my container. But when I download it and try to open it, I get the following error: "Windows cannot open the folder. The compressed (zipped) folder is invalid". But the saved zipped file in my application directory can be unzipped fine and contains my xml file. What am I doing wrong?

ArsenalRocks
  • 339
  • 1
  • 4
  • 12
  • Does the stream need to be flushed? The filestream seems to be redundant here, but I presume that it's in place for testing? – Brendan Green Apr 02 '20 at 23:16
  • @BrendanGreen I tried flushing both streams but no luck. The filestream is present here for testing but in reality I am using a MemoryStream there because the `blob.UploadFromStream` function does not like the ZipOutputStream for some reason. I get an empty zip file if I just pass in the ZipOutputStream directly. – ArsenalRocks Apr 02 '20 at 23:49

1 Answers1

2

I am able to reproduce the problem you're having. Essentially the issue is that the content is not completely written in the zip file when you initiated the upload command. In my test, the zip file size on the local disk was 902 bytes however at the time of uploading the size of file stream was just 40 bytes and that's causing the problem.

What I did was split the two functionality where the first one just creates the file and other reads from file and uploads in storage. Here's the code I used:

        CloudStorageAccount storageAccount = CloudStorageAccount.Parse("UseDevelopmentStorage=true");
        var cloudBlobClient = storageAccount.CreateCloudBlobClient();
        var cloudBlobContainer = cloudBlobClient.GetContainerReference("test");
        cloudBlobContainer.CreateIfNotExists();
        using (var fs = File.Create("test.zip"))
        {
            using (var s = new ZipOutputStream(fs))
            {
                s.PutNextEntry("entry1.xml");
                byte[] buffer = File.ReadAllBytes(@"Path\To\MyFile.txt");
                s.Write(buffer, 0, buffer.Length);
                //Get the blob ref
            }
        }
        using (var fs = File.OpenRead("test.zip"))
        {
            var blob = cloudBlobContainer.GetBlockBlobReference("test.zip");
            blob.Properties.ContentEncoding = "zip";
            blob.Properties.ContentType = "text/plain";
            blob.Metadata["filename"] = "test.zip";
            fs.Position = 0;
            blob.UploadFromStream(fs);
        }
Gaurav Mantri
  • 128,066
  • 12
  • 206
  • 241