chandra sekhar
chandra sekhar

Reputation: 1213

Azure blob file got corrupted post uploading file using UploadFromStreamAsync

I tried below code to upload file to azure blob container but uploaded file got corrupted.

 public async void UploadFile(Stream memoryStream, string fileName, string containerName)
    {
        try
        {
             memoryStream.Position = 0;
            CloudBlockBlob file = GetBlockBlobContainer(containerName).GetBlockBlobReference(fileName);
            file.Metadata["FileType"] = Path.GetExtension(fileName);
            file.Metadata["Name"] = fileName;
           await file.UploadFromStreamAsync(memoryStream).ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

How can I resolve it.

Unable to open excel file which was uploaded to blob using above code.

Error:

enter image description here

     Stream streamData= ConvertDataSetToByteArray(sourceTable); // sourceTable is the DataTable
                     streamData.Position = 0;

UploadFile(streamData,'ABCD.xlsx','sampleBlobContainer'); //calling logic to upload stream to blob

       private Stream ConvertDataSetToByteArray(DataTable dataTable)
            {

                StringBuilder sb = new StringBuilder();
                IEnumerable<string> columnNames = dataTable.Columns.Cast<DataColumn>().
                                                  Select(column => column.ColumnName);
                sb.AppendLine(string.Join(",", columnNames));

                foreach (DataRow row in dataTable.Rows)
                {
                    IEnumerable<string> fields = row.ItemArray.Select(field => (field.ToString()));
                    sb.AppendLine(string.Join(",", fields));
                }

                var myByteArray = System.Text.Encoding.UTF8.GetBytes(sb.ToString());

                var streamData = new MemoryStream(myByteArray);

                return streamData;
            }

Upvotes: 2

Views: 3651

Answers (4)

Tam&#225;s Deme
Tam&#225;s Deme

Reputation: 2228

Your code above creates a .csv file, not an .xlsx file. You can easily test this out by creating something similar to what your code builds, e.g.:

test.txt contents

Then if you rename it to .xlsx, to replicate what you do, you get:

excel result for opening text.xlsx

You have two solutions:

  1. You either need to build an actual .xlsx file, you can do this with the https://github.com/JanKallman/EPPlus package for example

or

  1. You need to save your file as a .csv, because that's what it really is.

The fact the you upload it to azure blob storage is completely irrelevant here - there's no issue with the upload.

Upvotes: 1

suziki
suziki

Reputation: 14088

It seems that your method don't have fatal problems. I guess the part of your Stream conversion has gone wrong.

This is my code:

using System;
using System.IO;
using Microsoft.WindowsAzure.Storage;

namespace ConsoleApp7
{
    class Program
    {
        public static class Util
        {
            public async static void UploadFile(Stream memoryStream, string fileName, string containerName)
            {
                memoryStream.Position = 0;
                var storageAccount = CloudStorageAccount.Parse("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
                var blockBlob = storageAccount.CreateCloudBlobClient()
                    .GetContainerReference(containerName)
                    .GetBlockBlobReference(fileName);
                blockBlob.UploadFromStreamAsync(memoryStream);
            }
        }
        static void Main(string[] args)
        {
            //Open the file
            FileStream fileStream = new FileStream("C:\\Users\\bowmanzh\\Desktop\\Book1.xlsx", FileMode.Open);

            //Read the byte[] of File
            byte[] bytes = new byte[fileStream.Length];
            fileStream.Read(bytes,0,bytes.Length);
            fileStream.Close();

            //turn from byte[] to Stream
            Stream stream = new MemoryStream(bytes);

            Util.UploadFile(stream,"Book2.xlsx","test");
            Console.WriteLine("Hello World!");
            Console.ReadLine();
        }
    }
}

enter image description here enter image description here enter image description here [1]: https://i.sstatic.net/MH7s3.jpg

Upvotes: 0

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131463

First of all, are you sure the file got corrupted? Save both the MemoryStream contents and the blog to local files and compare them. You could also save the MemoryStream contents to a file and use UploadFromFileAsync.

To check for actual corruption you should calculate the content's MD5 hash in advance and compare it with the blob's hash after upload.

To calculate the stream's MD5 hash use ComputeHash.

var hasher=MD5.Create();
 memoryStream.Position = 0;
var originalHash=Convert.ToBase64String(hasher.ComputeHash(memoryStream));

To get the client to calculate an blob has you need to set the BlobRequestOptions.StoreBlobContentMD5 option while uploading :

memoryStream.Position = 0;
var options = new BlobRequestOptions()
        {
            StoreBlobContentMD5 = testMd5
        };
await file.UploadFromStreamAsync(memoryStream,null,options,null).ConfigureAwait(false);

To retrieve and check the uploaded hash use FetchAttributes or FetchAttributesAsync and compare the BlobProperties.ContentMD5 value with the original :

file.FetchAttributes();
var blobHash=file.Properties.ContentMD5;
if (blobHash != originalHash)
{
   //Ouch! Retry perhaps?
}

Upvotes: 0

bzLoLIp0p
bzLoLIp0p

Reputation: 91

Since the stream is instantiated outside this method I assume the file is handled there and added to the stream, however, here you are returning the position of the stream to 0, thus invalidating the file.

Upvotes: 0

Related Questions