Different Azure blob streams when using .Net client vs. REST interface
- by knightpfhor
I have encountered an unusual difference in the way that the .Net client for Azure and the direct REST API bring back streams of binary data. If I use the CloundBlob.DownloadToStream() vs. getting the response stream from the HTTP response, I get streams with the same length, but different content. Specifically the REST response seems to 0 out a series of bytes.
I've discovered this issue because I'm trying to use the byte range feature for blobs which is currently not supported in the .Net client (if I'm wrong on this point and someone can point at where I can do this it might make the rest of this question irrelevant).
If I upload a binary representation of the first 2k unicode characters with this code:
Public Sub WriteFoo()
Dim Blob As CloudBlob
Dim Stream1 As MemoryStream
Dim Container As CloudBlobContainer
Dim Builder As StringBuilder
Dim NextCharacter As String
Dim Formatter As BinaryFormatter
Container = CloudStorageAccount.DevelopmentStorageAccount.CreateCloudBlobClient.GetContainerReference("testcontainer")
Container.CreateIfNotExist()
Blob = Container.GetBlobReference("Foo")
Stream1 = New MemoryStream()
Builder = New Text.StringBuilder()
For Index As Integer = 1 To 2000
Select Case Index
Case Is <= 9
NextCharacter = ChrW(9)
Case Is <= 31
NextCharacter = Environment.NewLine
Case 127
NextCharacter = Environment.NewLine
Case Else
NextCharacter = ChrW(Index)
End Select
Builder.Append(NextCharacter)
Next
Formatter = New BinaryFormatter()
Formatter.Serialize(Stream1, Builder.ToString())
Stream1.Position = 0
Blob.UploadFromStream(Stream1)
End Sub
Then try to access it with the following code:
Public Sub ReadFoo()
Dim Blob As CloudBlob
Dim Request As System.Net.HttpWebRequest
Dim Response As System.Net.WebResponse
Dim ResponseSize As Integer
Dim ResponseBuffer As Byte()
Dim ResponseStream As Stream
Dim Stream1 As MemoryStream
Dim Stream2 As MemoryStream
Dim Container As CloudBlobContainer
Dim Byte1 As Integer
Dim Byte2 As Integer
Container = CloudStorageAccount.DevelopmentStorageAccount.CreateCloudBlobClient.GetContainerReference("testcontainer")
Container.CreateIfNotExist()
Blob = Container.GetBlobReference("Foo")
Stream1 = New MemoryStream()
Stream2 = New MemoryStream()
Blob.DownloadToStream(Stream1)
Request = DirectCast(System.Net.WebRequest.Create(Blob.Uri), System.Net.HttpWebRequest)
Request.Headers.Add("x-ms-version", "2009-09-19")
Request.Headers.Add("x-ms-range", String.Format("bytes={0}-{1}", 0, Integer.MaxValue))
Blob.Container.ServiceClient.Credentials.SignRequest(Request)
Response = Request.GetResponse()
ResponseStream = Response.GetResponseStream()
ResponseSize = CInt(Response.ContentLength)
ReDim ResponseBuffer(ResponseSize - 1)
ResponseStream.Read(ResponseBuffer, 0, ResponseSize)
Stream2.Write(ResponseBuffer, 0, ResponseSize)
Stream1.Position = 0
Stream2.Position = 0
If Stream1.Length <> Stream2.Length Then
System.Diagnostics.Debug.WriteLine(String.Format("Streams a different length. 1: {0}. 2: {1}", Stream1.Length, Stream2.Length))
Else
While Stream1.Position < Stream1.Length
Byte1 = Stream1.ReadByte()
Byte2 = Stream2.ReadByte()
If Byte1 <> Byte2 Then
System.Diagnostics.Debug.WriteLine(String.Format("Streams differ at position {0}, 1: {1}. 2: {2}", Stream1.Position - 1, Byte1, Byte2))
End If
End While
End If
End Sub
Past all certain point all of the data in Stream2 (the data I've retrieved from the REST api) ends up being 0. To make matters even more confusing, when I reverse the order that I put the characters in the string e.g. For Index As Integer = 2000 To 1 rather than For Index As Integer = 1To 2000 it all works OK.
Any help is much appreciated. My computer is sick of me swearing at it.