Search code examples
vb.nettwitterhttpwebrequest

Twitter upload/media Append


I just can't wrap my mind around how to do the append step. I've already done the INIT part without trouble but I don't understand how to do the next step.

What I'm doing now : I build a authorization header with only the oauth parameters and the signature base too, then I put the required parameters into the body request : command=APPEND, media_id from the INIT method, media with the raw binary image, and segment_index=0 because I have to send only one request since the size of my image is never more than 30 kB.

I have tried the following:

        Dim oHttpWebRequest As HttpWebRequest
        Dim oHttpWebResponse As HttpWebResponse
        Dim oStream As Stream
        Dim newLine As String = System.Environment.NewLine
        Dim mediaId = getINITresponse()
        Try
            oHttpWebRequest = DirectCast(WebRequest.Create("https://upload.twitter.com/1.1/media/upload.json"), HttpWebRequest)

            Dim sBody As String = buildHeader(twitter, sAuth)
            oHttpWebRequest.Headers.Add("Authorization", sBody)
            oHttpWebRequest.Method = "POST"

            Dim sBoundary As String = DateTime.Now.Ticks.ToString("x")
            Dim sStartBoundary As String = "--" + sBoundary + newLine
            Dim sEndBoundary As String = newLine + "--" + sBoundary + "--" + newLine

            oHttpWebRequest.ContentType = "multipart/form-data; boundary=" + sBoundary

            Dim sBodyData As String = ""
            Dim srequestString As New StringBuilder()
            sBodyData = "command=APPEND&media_id=" + mediaId + "&segment_index=0&media="
            srequestString.AppendLine(sStartBoundary + "Content-Disposition: form-data; name=""media""; filename=""image.jpg""" + newLine)
            srequestString.AppendLine(Encoding.Default.GetString(getBinaryFileFromPath(sFicName)))
            srequestString.AppendLine(newLine + sEndBoundary + newLine)

            Dim postData As Byte()
            postData = Text.Encoding.UTF8.GetBytes(sBodyData)
            Dim postDataBytes As Byte()
            postDataBytes = Text.Encoding.UTF8.GetBytes(srequestString.ToString()) 
            Dim byteResult() As Byte = postData.Concat(postDataBytes).ToArray()   

            oHttpWebRequest.ContentLength = byteResult.Length
            Using requestStream = oHttpWebRequest.GetRequestStream()
                requestStream.Write(byteResult, 0, byteResult.Length)
                requestStream.Close()
            End Using

            oHttpWebResponse = DirectCast(oHttpWebRequest.GetResponse(), HttpWebResponse)
            oStream = oHttpWebResponse.GetResponseStream()

            Return New StreamReader(oStream, Encoding.UTF8).ReadToEnd()

        Catch wex As WebException 'Exception venant du serveur distant
            Return New StreamReader(wex.Response.GetResponseStream()).ReadToEnd()
        End Try

My Init part is working and I save the media_id and use it for the Append part. My image is no more than 30 kB so it's not a problem of size.

Twitter respond me with the status : 400 Bad Request.

I don't know what I am doing wrong. Sorry for my bad english!


Solution

  • I find the answer:

    sBodyData = "command=APPEND&media_id=" + mediaId + "&segment_index=0&media="
    

    I was making my body data as if I was sending a request with ContentType=application/x-www-form-urlencoded. So I used both of the contentType in the same request and of course it wasn't working. Now it looks like that:

    Dim newLine As String = System.Environment.NewLine
    
    srequestString.AppendLine(sStartBoundary + "Content-Disposition: form-data; name=""command""" + newLine)
    srequestString.AppendLine("APPEND")
    srequestString.AppendLine(sStartBoundary + "Content-Disposition: form-data; name=""media_id""" + newLine)
    srequestString.AppendLine(mediaId)
    srequestString.AppendLine(sStartBoundary + "Content-Disposition: form-data; name=""media""" + newLine)
    srequestString.AppendLine(Encoding.Default.GetString(getBinaryFileFromPath(sFileName)))
    srequestString.AppendLine(sStartBoundary + "Content-Disposition: form-data; name=""segment_index""" + newLine)
    srequestString.AppendLine("0")
    srequestString.AppendLine(sEndBoundary)