BigBastis Blog

VB.NET: Bilder Hochladen mit der TwitPic API Teil 3

Introduction

user

Sebastian Gross

Sebastian Gross arbeitet in Bielefeld als Softwareentwickler für .NET und Java im Bereich Web.Als Fan der .NET-Plattform lässt er sich kein Userguppen Treffen und Community Event im Raum OWL entgehen.Dabei hat er eine besondere Vorliebe für das ASP.NET MVC Framework und für das Test Driven Development (TDD) entwickelt.


LATEST POSTS

Handling too long scrollspy menus 10th June, 2015

Java: Create ZIP archive 23rd March, 2015

.NET

VB.NET: Bilder Hochladen mit der TwitPic API Teil 3

Posted on .

In dem dritten Teil der API-Reihe möchte ich euch zeigen wie man mit Hilfe der TwitPic API Bilder hochladen kann.

Diesesmal schreibt die API vor, dass man POST-Requests verwendet um der Seite Daten zu senden. Das macht die Sache etwas komplizierter, und dazu kommt noch, dass wir auch noch ein Bild verschicken müssen, also müssen auchnoch binäre Daten verschickt werden. Aber langsam, erstmal die Theorie!

Ihr kennt doch sicher die normalen Eingabemasken wie zB. die von imageshack.us. Diese besteht aus einem Dateiauswahlfeld, mehreren Checkboxen und einem Textfeld. Wer schonmal HTML gemacht hat wird wissen dass dieses Gebilde aus so genannten Interaktiven Elementen ein Formular darstellt welches nach dem Betätigen des Senden-Buttons an eine vorher definierte Adresse gesendet wird!

Dabei sendet der Browser einen HTTP POST-Request an den Server. Ein solcher Request besteht für gewöhnlich aus einem Kopf, den Daten und einem Fuß. So könnte zB. ein HTTP POST-Request aussehen:

POST /wiki/Spezial:Search HTTP/1.1
Host: de.wikipedia.org
Content-Type: application/x-www-form-urlencoded
Content-Length: 24
search=Katzen&go=Artikel

Der Server verwertet diese Daten dann und schickt eine Antwort. Je nachdem wie wir angefragt haben bekommen wir als Antwort eine XML-Struktur (Wie in den Letzten Beispielen) oder eine HTML Struktur. Die Kommunikation geschieht dabei auf dem HTTP Port 80 und läuft über das TCP Protokoll!

In den letzten beiden Teilen haben wir jeweils so genannte GET-Requests erstellt, bei denen nur der URL-Strang mit den Variablen versandt wurde.

Da wir aber nun ein Bild übertragen wollen, müssen wir versuchen ein POST-Request-Objekt zu erstellen, das wir dann an den TwitPic Server schicken können.

Unser POST-Objekt muss dabei folgende Daten übermitteln:

  • Unseren Twitter Benutzernamen
  • Unser Twitter Passwort
  • Das Bild das wir einstellen wollen

Wenn wir diese Daten nun in unser Objekt verfrachten, müssen wir dafür sorgen, dass der Server später weis, was was ist und die Daten von einander trennen kann. Deswegen müssen wir für jeden Eintrag einen eigenen Head und Body erzeugen.

Das Bild muss dann auch in das binäre Format umgewandelt werden und dann mit den anderen Daten durch ein Strom an den Server gesendet werden! – Hört sich kompliziert an, ich weis aber es hält sich in Grenzen!

Hier erstmal der Code für das Hochladen des Objekts mit allen Daten und der Abruf der Antwort. Tipp: Ihr könnt den Code besser lesen, wenn ihr auf den Knopf oben rechts in der Code Darstellung klickt!

    Public Function uploadPic(ByVal pic As Byte(), ByVal filename As String, ByVal user As String, ByVal pass As String)
        Dim encoding As String = "iso-8859-1"

        'Erzeugen einer einzigartigen identifikation
        Dim gui As String = Guid.NewGuid().ToString()

        'Diese wird für den Header und den footer der Daten benötigt
        Dim head As String = String.Format("--{0}", gui)
        Dim foot As String = String.Format("--{0}--", gui)

        'Einen Stringbuilder erstellen, in dem wir nun bequem die
        'benötigten POST Daten speichern können
        Dim contents As StringBuilder = New StringBuilder()

        'Benutzerdaten schreiben (benutzername)
        contents.AppendLine(head)
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=""{0}""", "username"))
        contents.AppendLine()
        contents.AppendLine(user)

        'Benutzerdaten schreiben (passwort)
        contents.AppendLine(head)
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=""{0}""", "password"))
        contents.AppendLine()
        contents.AppendLine(pass)

        'Header schreiben
        contents.AppendLine(head)
        'Bildinformationen schreiben, Bildkopf und die Binärdaten
        Dim fileHeader As String = String.Format("Content-Disposition: file; name=""{0}""; filename=""{1}""", "media", filename)
        Dim fileData As String = System.Text.Encoding.GetEncoding(encoding).GetString(pic)

        'Informationen zu dem Übergebenen Dateityp schreiben
        contents.AppendLine(fileHeader)
        contents.AppendLine(String.Format("Content-Type: {0}", "image/jpeg"))
        contents.AppendLine()
        contents.AppendLine(fileData)

        'Durch schreiben des footers signalisieren dass keine Daten mehr kommen
        contents.AppendLine(foot)

        MessageBox.Show(contents.ToString)

        'Stream Reader zum lesen der Antwort von Twitpic
        Dim reader As StreamReader
        Dim result As String
        Dim response As HttpWebResponse

        'Einen Webrequest zu der TwitPic API erstellen
        Dim request As HttpWebRequest = WebRequest.Create("http://twitpic.com/api/upload")

        'Die Auflagen die in der API beschreiben sind erfüllen:
        'API-Zitat:
        '---
        'Fields to post in:
        '(post data should be formatted as multipart/form-data)
        '---
        request.ContentType = String.Format("multipart/form-data; boundary={0}", gui)
        request.Method = "POST"

        'Die Daten die noch im Stringbuilder als String vorliegen
        'in das byte (Binär)-Format umwandeln, damit die API diese annimt
        Dim bytes As Byte() = System.Text.Encoding.GetEncoding(encoding).GetBytes(contents.ToString())
        request.ContentLength = bytes.Length

        'Einen Stream aus dem WebRequest erstellen
        Dim writer As Stream = request.GetRequestStream()

        'Die Binären Daten in den Strom schreiben
        writer.Write(bytes, 0, bytes.Length)
        response = request.GetResponse()

        'Antwort von Twitpic empfangen
        reader = New StreamReader(response.GetResponseStream)
        result = reader.ReadToEnd

        reader.Close()

        Return result
    End Function

bild1Wenn ihr diesen Code ausführt, wird ein POST-Objekt erzeugt und an den TwitPic Server gesendet. Dabei werden diese Informationen übermittelt. (Bild 1)

Man sieht ganz klar die Aufteilung. Der Kopf der aus der UID und den Meta Daten besteht und der Body, der nur den Wert beinhaltet.

Das Bild das ich hier sende hat einen etwas größeren Kopf, scheint dafür aber einen sehr kleinen Body zu haben. Ich kann euch beruhigen, das ist nur so, weil Windows, oder das MessageBox Objekt keine Binäre Darstellung von Zeichen beherrscht.

Eigentlich kommt dadrunter noch ein Footer (Fuß), aber dieser wird wegen der binären Daten abgeschnitten!

bild2Natürlich bekommt man auch eine Antwort, in diesem Fall eine im XML-Format. Diese beinhaltet entweder die Erfolgsmeldung oder eine Fehlermeldung mit einer Kurzen Beschreibung, woran es lag. An Bild 2 könnt ihr erkennen wie so ein Fehler aussehen könnte!

Wenn kein Fehler kommt steht dort dementsprechend die URL zum Bild statt der Fehlermeldung!

Wenn ihr nicht direkt den Code versteht ist das nicht schlimm. Man sollte ersteinmal wissen was der Browser da bei jedem Klick eigentlich hin- und herschickt. Dazu kann ich den Wikipedia-Artikel empfehlen. Es schadet auch nicht, weitere Beispiele anzuschauen bei denen mit HTTPWebRequest gearbeitet wird. ZB Hier oder Hier. (leider alles in C#)

Zum Schluss sei hier noch gesagt, dass die TwitPic API noch weitere Möglichkeiten bietet, wie zB. das Anfertigen von Vorschaubildern oder das Anhängen von Tweets an das Bild sodass automatisch auch euer Twitter Status mit dem neuen Bild aktualisiert wird!

bild3Bild 3: Das Demoprojekt in Aktion

Wie immer könnt ihr euch auch das Demoprojekt herunterladen: Download

Ich hoffe das Beispiel hat euch gefallen und freue mich auf euer Feedback!

profile

Sebastian Gross

http://www.bigbasti.com

Sebastian Gross arbeitet in Bielefeld als Softwareentwickler für .NET und Java im Bereich Web.Als Fan der .NET-Plattform lässt er sich kein Userguppen Treffen und Community Event im Raum OWL entgehen.Dabei hat er eine besondere Vorliebe für das ASP.NET MVC Framework und für das Test Driven Development (TDD) entwickelt.

Comments
user

Author Pascal Raszyk

Posted at 10:12 26. Januar 2010.

Sehr schöner Artikel. Habe schon seit längerem so etwas gesucht.
Wird die Verbindung über Sockets hergestellt?

user

Author admin

Posted at 15:38 26. Januar 2010.

Hallo Pascal,
ja die Kommunikation verläuft hierbei über TCP und hier werden die Verbindungen über Sockets geregelt. Also ja. 🙂
MfG, Basti

Kommentar verfassen

View Comments (2) ...
Navigation