Reputation: 1606
I want to upload to my azure local development account directly using a stream. I have created a class for azure blob storage.
public class AzureBlob
{
delegate void UploadFinished(IAsyncResult result);
public void uploadFile()
{
//Initial configuration
CloudStorage account = CloudStorageAccount.DevelopmentStorageAccount;
CloudBlobClient client = account.CreateBlobClient();
CloudBlobContainer container = client.GetContainerReference("myfiles");
Stream stream = new MemoryStream();
//Upload to azure
CloudBlob blob = container.GetBlobReference("sample.txt");
UploadFinished uploadFinished = delegate(IAsyncResult result)
{
Console.WriteLine("Upload finished {0} {1}", result.IsCompleted, stream.Position);
};
blob.BeginUploadFromStream(stream, new AsyncCallback(uploadFinished));
//Write to stream
for(int i=0;i<100;i++)
{
for(int j=0;j<50;j++)
{
stream.WriteByte(65);
}
}
stream.Close();
}
}
The first problem that i face is i get the file in the storage but it contains no data. Even if i use EndOfUploadStream method in the callback (which according to some stackoverflow answer is a solution). Secondly, i put the break point inside the callback and i found that the callback gets executed once, before i close the stream, and the program keeps updating the stream. At this point the stream position is around 913(mostly random). Please help me in uploading the blob directly through the stream asynchronously.
Upvotes: 2
Views: 4035
Reputation: 12174
great answer from smarx! Also, move stream.Close() into the callback.
delegate void BeginUploadFinished(IAsyncResult result);
public void UploadFile()
{
//Initial configuration
var account = CloudStorageAccount.DevelopmentStorageAccount;
var client = account.CreateCloudBlobClient();
var container = client.GetContainerReference("myfiles");
Stream stream = new MemoryStream();
var state = new Object{};
//Upload to azure
var blob = container.GetBlobReference("test.txt");
BeginUploadFinished beginUploadFinished = delegate(IAsyncResult result)
{
blob.EndUploadFromStream(result);
Trace.WriteLine("EndUploadFromStream", "Information");
stream.Close();
stream.Dispose();
};
//Write to stream
Trace.WriteLine("Writing Stream", "Information");
for (var i = 0; i < 100; i++)
{
for (var j = 0; j < 50; j++)
{
stream.WriteByte(65);
}
}
stream.Seek(0, SeekOrigin.Begin);
Trace.WriteLine("BeginUploadFromStream", "Information");
var _result = blob.BeginUploadFromStream(stream, new AsyncCallback(beginUploadFinished), state);
_result.AsyncWaitHandle.WaitOne();
}
Upvotes: 2
Reputation: 60153
It looks to me like you have a race condition. You start uploading the stream before you've actually put content into it.
You probably want something like this:
Stream stream = new MemoryStream();
//Write to stream
for(int i=0;i<100;i++)
{
for(int j=0;j<50;j++)
{
stream.WriteByte(65);
}
}
stream.SetPosition(0); // <-- need to reset stream position to 0 before uploading
//Upload to azure
CloudBlob blob = container.GetBlobReference("sample.txt");
UploadFinished uploadFinished = delegate(IAsyncResult result)
{
blob.EndUploadFromStream(result); // <-- have to call this in your handler
Console.WriteLine("Upload finished {0} {1}", result.IsCompleted, stream.Position);
};
blob.BeginUploadFromStream(stream, new AsyncCallback(uploadFinished));
Upvotes: 2