Wenn Windows 8 Tablet Geräte schon eine Kamera haben, dann sollte man Bilder auch auf eine Website hochladen können. Folgendes VB.NET Beispiel zeigt das auch, Es zeigt aber auch, zum wiederholten male, die Grenzen von WinrRt und .NET.
Zentrale Frage war unter anderem auch wie konvertiert man einen Stream nach IRandomAccessStream und umgekehrt. Ersteres liegt im .NET System.IO Namensraum und zweiteres im Windows.Storage.Streams. Die Wahrheit ist, es ist mir bis zum Schluss nicht gelungen ohne aufwendig Byte Arrays dazwischen schieben zu müssen.
File Upload
Für das Hochladen einer Bilddatei habe ich einen ASHX Handler geschrieben, den ich schon in einem Blog Post verwendetet habe. Dort war es relativ einfach den Stream zu verarbeiten.
Dieses METRO Code Sample holt sich das JPG Bild aber von der lokalen Festplatte. IBuffer als Winrt Typ kann aber nicht direkt in einem HTTP Send übergeben werden. Dazu benötigt man die Helper Klasse AsStream. Leider nicht in WinRT enthalten, sondern eben per Extension Methode über den Namensraum System.Runtime.InteropServices.WindowsRuntime einzubinden. Das Problem dabei ist, das Visual Studio 11 Intellisense das nicht vorschlägt, sondern das man das Wissen muss. Ein ungewohnter Zustand.
Dim url As New Uri("http://win8-pre9/lab1/upload1.ashx?datei=" & Date.Now.Ticks)
wait1.IsActive = True
Dim fs = Await KnownFolders.PicturesLibrary.GetFileAsync("world.jpg")
Dim b As IBuffer = Await FileIO.ReadBufferAsync(fs)
Dim sc As StreamContent = New StreamContent(b.AsStream) 'asstream extension methode aus System.Runtime.InteropServices.WindowsRuntime
Dim http As New HttpClient()
Dim req As HttpRequestMessage = New HttpRequestMessage(HttpMethod.Post, url)
req.Content = sc
Dim resp As HttpResponseMessage = Await http.SendAsync(req)
wait1.IsActive = False
Dim msg As MessageDialog = New MessageDialog(Await resp.Content.ReadAsStringAsync)
Await msg.ShowAsync()
Der Rest gestaltet sich ganz einfach. Mit dem HTTPClient ein Post absenden und dabei den Stream hier als StreamContent übergeben.
ait1 ist ein XAML Progressring Steuerelement, das ich so ein und ausblende.
Datei herunterladen/Download
Bei diesem VB/NET WinRT Beispiel habe ich schon an mir zu Zweifeln beginnen, Wie lade ich ein Bild und zeige es an? Das man ein Image Control braucht und ein BitmapImage Objekt, kannte ich aus Silverlight.
Der Download mit HttpClient statt Webclient war mir auch bekannt. Es waren die beiden Zeilen dazwischen, die es in sich hatten. Erstens zeigt mir Bitampimage an, das es gerne ein IRandomAccessStream hätte (Winrt) und Resp ist wieder ein System.IO Stream. über den kleine Zwischenweg des InMemoryRandomaccessStream und der Extension Methode asStreamForWrite, klappt es dann doch ganz einfach. Aber ohne die Helper Klasse aus WindowsRuntimeStreamExtensions wären das ungleich mehr Code Zeilen geworden
wait1.IsActive = True
Dim url As New Uri("http://win8-pre9/lab1/images/welt.jpg")
Dim http As New HttpClient()
Dim resp As Stream = Await http.GetStreamAsync(url)
Dim ras = New InMemoryRandomAccessStream()
Await resp.CopyToAsync(ras.AsStreamForWrite()) 'Imports System.IO.WindowsRuntimeStreamExtensions
Dim bi As BitmapImage = New BitmapImage()
bi.SetSource(ras)
image1.Source = bi
wait1.IsActive = False
Kleines Fazit. Die Jungs bei Microsoft aus der WinDiv die für das WinRT verantwortlich sind, haben wenig Ahnung oder Rücksicht genommen auf die Belange der DevDiv (die .NET gemacht haben). Mit Hilfe der Helper Klassen wird nun versucht dies zu korrigieren.