Join Michael Lehman for an in-depth discussion in this video Cloud Notes app: Uploading blobs to save our images, part of Building Windows Phone 8 Apps with Azure.
Alright, now we've got a picture path property, inside of our note model, our entity. We have a way of getting a picture from the camera. Let's go ahead an connect up to Azure blob storage in our connect to Azure method. An then we'll update the logic to actually upload the picture when you take one. And finally after you've taken one, we'll use a web browser, to go see if we can download that image and take a look at it. So, let's open up notes model, select, Connect to Windows Azure. And just as we created a table client and a table object, let's go ahead and do a similar set of things for blobs.
So, we create a blob client from the account. Create Cloud Blob Client. Now, we don't have Blob Client defined. So let's go to the top, and just as we did for Cloud Table Client and Cloud Table, let's go ahead and create a Cloud Blob Client and a Cloud Blob Container. You try saying that five times fast. CloudBlobClient BlobClient. Now we have to resolve that and we're going to resolve that with Microsoft.WindowsAzure.Storage.Blob, and now we can put in CloudBlobContainer blobContainer.
Remember, all your blobs go in a container, which is kind of like a table except that each blob in the container has a unique name. Alright, so now we've got a cloud blob client and a cloud blob container object. Let's go back to connect to Windows Azure. And we now got the cloud blobclient, let's go ahead and connect up here. So, we need to next to create a cloud blob container instance, so we will say blob container equals blobclient.getcontainerreference and we'll call our reference container one.
Then we'll get rid of this extraneous backslash there. Now, just to prove that we're actually creating something in our storage emulator, we'll go to Server Explorer>Windows Azure>devstore account1>Blobs and see, we don't have any blobs underneath there. So, let's go ahead and do the one last bit we have to do here, which is similar to the way we did with tables. We have to say 08blobcontainer.create if not exist async. Alright, now having done that, we can go ahead and run this and the first time we run it; it's going to create a container. Alright.
We'll stop. Go to the server explorer. Refresh Blobs, and voila container one. If we go into container one, we can see that we don't have any blobs in it. But we can see what each blob will have. It will have a name, a size, a last modified date again. At the proper time of our friends in Greenwitch, England. A content type and a URL. Now the content type is very important. We want to try to download things into a web browser. This is the standard internet content type of things like index/jpeg, or index/image, or application/octet-stream.
In our case, we're going to make sure that we set it to an image content type, so that a web browser knows what to do with it. But we're getting a little ahead of ourselves. Let's go ahead, and now that we're connected up here, let's go ahead and go into our camera task logic, and let's make sure that we can go ahead and convert our image from a bitmap into a byte array so that we can use the appropriate API to upload to Windows Azure. So, we're going to go over to our editor page and open up the C-sharp file.
Notice here we have a note model object entitled our note, and when we leave the editor page here in on navigated from, starting on line 39, we call update note. So as long as our camera completed handler updates things into our note. We can make sure that we decide to update the data back to Windows Azure back inside notes model. So here is how we connect the dots, but first of all we're going to write a message, we'll turn off this break point, We're going to write a method here to convert that bitmap that we get from the camera into a byte array.
And we're going to do that by saying byte ConvertImageToBytes, and pass in a BitmapImage, and we're going to convert that using streams. We're going to say, byte array data equals null and return data. That's great that that arrays is empty, now let's put some data into it. So, we're going to say, using MemoryStream stream equals new MemoryStream. And we're going to say WriteableBitmap. W bitmap equals new writable bitmap and pass in our existing bitmap.
And we have to right click here and resolve this to system.io. And then, we need to use wbitmap.save jpeg and pass in our stream. Our bitmap pixel width and pixel height. And then we want to pass in our orientation, and our quality, 100%. So that now writes it to the stream, now we're going to say stream.seek 0, seekorigin.begin, alright? And now we need to say data equals stream.getbuffer, and there we go, now we've got our image converted from a bit map image to a byte array, which is what we need to upload to Windows Azure.
Now we need to call that here. We've set the source of our bitmap from the, is what we got from the camera, now we can say byte array image as bytes equals convert image to bytes and pass in our BMP. Alright. So far, so good for that. Now, what do we do with the bytes? Well, we have to have some way of passing them back from the editor page, here, back to the notes model. A couple of different ways we could do that, but I think the easiest way is to add a new signature for update note that also passes in the byte array, if we happen to have one.
So let's go ahead and do that. We'll come back to notes model. We'll go to Update Note, and it'll create another signature for Update Note. Be just like this, but we'll say, it also happens to have a byte array as an option. And so, we're first going to go ahead and upload the blob to Windows Azure. An then we'll call the other signature for update note, and pass in, the note in order to update it. We get the green squiggles here because we don't have any array operators.
But believe me, very shortly, we will. Alright, it's time to go ahead an upload our blob. An the way we're going to do that, is we're going to go ahead and create a blob reference inside update note. This version here, so we're going to go ahead and we've got the object, note to update. So we're going to say CloudBlockBlob blockBlob is equal to our blob container, .get BlockBlob reference, and what we're going to pass in is our note to update.ID.
So that's going to be the key we're going to be using inside Windows Azure blob storage for each one of these blobs and we need to set the block blob properties content type so we'll go blockblob.properties.content type and we're going to set that equal to image/jpeg. So the browsers will know that's a picture. And now we're going to upload this to Windows Azure blob storage. So we say await, lock blob.upload from bite array async. And we pass in the three things we need to pass in.
The image, index which is zero, and the length which is image.length. And now that we've uploaded the blob, we have something inside that blob that's going to allow us to now go and access that later. And that is, once you've done the upload, the block blob object now has the URI for that image in blob storage. So we're going to say, note to update.picturepath is equal to blockblob.URI.2string. Now when we call update note and just pass in the note.
It will update the table storage item with the picture path in blob storage, and of course this is async so we're going to await that one as well. Alright, so this should do it. We should be able to go into our code. We should be able to update, and we should be able to capture a picture, and when we come back here, inside Notes model, we're going to go ahead and upload the image. Let's double check to make sure, over here in Editor page, that we did the right thing. Well, actually we haven't done the right thing completely yet. What we want to do, is come back up here and put the byte array for our image, right here.
So we'll initialize it to null Down here instead of using image as bytes, we'll say image to upload. And that way, inside our on navigated from, we can make a decision as to which signature update note we want to call. So we'll say if imageToUpload is not equal to null, we'll say await App.ViewModel.UpdateNote, and we use the second signature, ourNote, and imageToUpload. Else, we use the original signature. There we go. Now if we have a new picture we'll upload the image, if we have an old picture we'll just leave it as it is.
All right, so let's go ahead and give this a try. There's our notes, let's go ahead and click on Note D. Let's click on the Add button. There's the dancing square, let's see if we can get it when it's blue. I bet maybe we got it when it's red, we'll find out. Click Accept and we'll click back. We'll come back to our server explorer and go look in our container and voila, we now have a blob that's named the same as our ID. It's eight k bytes, It's modified here at 11:00 p.m. In beautiful Greenwich, England. Its content type is image slash JPEG and here's its full URL pointing to our local server.
Now, let's see if we can go see it. Copy URL, open up a web browser, paste and hit Return. And, what happens? Resource not found? Well, what do you think's happening? Well, the answer is, blobs are private by default in Windows Azure blob storage. So, what we need to do is we need to make the blobs in our container public. So we'll stop execution of our app. We'll come back here and during our initialization of our blob container, in notes model, back up here in Connect to Windows Azure. After we've got our blob container, we'll set the blob container's properties.
So we'll say await blobContainer.SetPermissionsAsync and we have to pass that in a permissions object. So we'll pass in the permissions object by saying newBlobContainer ContainerPermissions and we'll pass in PublicAccess as the permission we want to set, and we'll set it to BlobContainerPublicAccessType.Blob. There we go and everything's good except we don't need this extraneous semi colon. All right, let's try it again. Maybe this time we can get a blue square.
If we time it right, let's go to C2. Click Add. And, click it about here. All right, maybe we got a blue one. Come back to our container. We'll click this little Refresh button. And lo and behold, we don't seem to have a record there, well why not? Well the reason is because we are still on the editor page. We have to do this in order to upload our blob. Now we will come back here and refresh it and there's the blob for the second one. So we are going to right click on this.
Copy URL, come back to our web browser. Paste it in and go. And lo and behold, there's a little red square. I guess we didn't get the blue one, because the timing of the sound apparently isn't exactly connected to the timing of the picture capture. But because we set the properties to public, we can now get this URL, come back to our web browser, paste that in. And there we got a blue square the first time, even though we thought we didn't. But, in any event, you can see how easy it is to capture something, upload it as a blob, and then associate it with something in your table storage.
Now, you can, with Windows Azure blob storage, get custom URLs to work with this, and so you don't have to expose the path to your, either your development server or your production server. That's beyond the scope of this course, but just know that you can, in fact, do that. Also know that we could have taken this image and put it inside of our table storage if the image was less than 64k. Remember every column in a row in Windows Azure Table Storage has to be 64k or less. So the reason we're using blob storage is in a real world situation where you're connecting to a device.
Your picture images may be megabytes in size, especially if you've got one of those Nokia Lumia 1025s with the 41 megapixel camera. So that's why we upload it to blob storage and then associate the picture path to the table storage. A, so we can share it, and B, so that we can store it in table storage, and retrieve it later at run time if we want to show the picture inside the UI. Alright, that's it of our exploration of blob storage. We've added a picture property. We've captured an image with the camera. And now we've uploaded it to Windows Azure blob storage, and associated it with our rows.
In our plain old notes database stored in Windows Azure table storage.
- What is Windows Azure?
- Creating Azure tables
- Inserting, updating, and deleting data in tables
- Uploading a blob to Windows Azure storage
- Using shared access signatures
- Implementing mobile services
- Adding push notifications