Search code examples
streamzipcloudazure-storageazure-storage-files

How do I increase the size of an Azure File Storage CloudFile before I know the file size?


I'm using Azure File Storage to store some files, and I want to create a zip file containing some of these files on the same Azure file share.

This is my code so far:

private void CreateZip(CloudFileDirectory directory) {

    if (directory == null) throw new ArgumentNullException(nameof(directory));

    var zipFilename = $"{directory.Name}.zip";

    var zip = directory.GetFileReference(zipFilename);
    if (!zip.Exists()) { 

        zip.Create(0);  // <-- I don't know what size its gonna be!!

        using (var zipStream = zip.OpenWrite(null))
        using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create)) {

            foreach (var file in directory.ListFilesAndDirectories().OfType<CloudFile>()) {
                if (file.Name.Equals(zipFilename, StringComparison.InvariantCultureIgnoreCase))
                    continue;                        

                using (var fileStream = file.OpenRead()) {

                    var entry = archive.CreateEntry(file.Name);
                    using (var entryStream = entry.Open())
                        fileStream.CopyTo(entryStream); // <-- exception is thrown
                }
            }
        }
    }
}

On the line zip.Create(0); this creates an empty file. I then go on to use this file reference to create a zip file, and add stuff to it, but when it gets to the fileStream.CopyTo(entryStream); it throws an exception with this message:

The remote server returned an error: (416) The range specified is invalid for the current size of the resource.

Presumably because the file size is 0 and it's unable to automatically increase the size.

I can create the file with int.MaxValue, but then I get a 2GB file. I can't even work out the size of the file I'm adding to the achive and resize the file to extend it by that amount, because its a zip and its gonna compress and change the file size.

How do I do this?


Solution

  • This issue is more related with System.IO.Compression. I have rewrite your code, please use memory stream instead like the following code. It works fine on my side. Hope it could give you some tips.

           public static void CreateZip(CloudFileDirectory directory)
            {
    
                if (directory == null) throw new ArgumentNullException(nameof(directory));
    
                var zipFilename = $"{directory.Name}.zip";          
                var zip = directory.GetFileReference(zipFilename);
                if (!zip.Exists())
                {
    
                    //zip.Create(600000);  // <-- I don't know what size its gonna be!!
    
                    using (var memoryStream = new MemoryStream())
                    {
                        using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
                        {
    
                            foreach (var file in directory.ListFilesAndDirectories().OfType<CloudFile>())
                            {
                                if (file.Name.Equals(zipFilename, StringComparison.InvariantCultureIgnoreCase))
                                    continue;
    
                                using (var fileStream = file.OpenRead())
                                {
    
                                    var entry = archive.CreateEntry(file.Name, CompressionLevel.Optimal);
                                    using (var entryStream = entry.Open())
                                    {
    
                                        fileStream.CopyTo(entryStream); // <-- exception is thrown
                                    }
    
                                }
                            }
                        }
                        memoryStream.Seek(0, SeekOrigin.Begin);
                        zip.UploadFromStream(memoryStream);
    
                    }
    
                }
            }