Question Submit a Form with Selected File using HTTPWebRequest

digitaldrew

Well-known member
Joined
Nov 10, 2012
Messages
167
Programming Experience
Beginner
I'm trying to have a program go through a list of websites and submit a form. The form has 3 fields: One is for a Title, one is to browse and select an image, and the third is to enter a website Url. I'd like to use HTTP web request to go through and submit the form on each page.

In my program I've created 3 text boxes. One of the text boxes has a button next to it with openfiledialog where the user selects the image they want to upload and it then inputs that location into the textbox.

I know I'm doing something wrong here because I'm passing the file location from the textbox as a string and I am certain it can't be that easy..lol. Regardless, my program seams to go through and work fine, but as expected, it tells me that each submission was unsuccessful. Here is some code:

When the doworker kicks off it should select the first checked website in the list and call the WRequest function.
VB.NET:
    Private Sub SubmitThread_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles SubmitThread.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        For i As Integer = 0 To Me.lstSubmissionSites.CheckedItems.Count - 1
            r = i
            Dim selectedSite As String = String.Empty
            selectedSite = lstSubmissionSites.Items(i).ToString
            If lstSubmissionSites.InvokeRequired Then
                lstSubmissionSites.Invoke(Sub() lstSubmissionSites.SelectedIndex = r)
            End If

            If TestThread.CancellationPending = True Then
                e.Cancel = True
                Exit For
            Else
                WRequest(selectedSite, "POST", "title=" & postTitle & "&picture=" & strFileName & "&source=" & sourceUrl & "")
                worker.ReportProgress(0, streamResponse)
            End If
        Next
    End Sub

Here is the WRequest function:

VB.NET:
    Function WRequest(URL As String, method As String, POSTdata As String) As String
        Try
            Dim hwrequest As Net.HttpWebRequest = Net.Webrequest.Create(URL)
            hwrequest.Accept = "*/*"
            hwrequest.AllowAutoRedirect = True
            hwrequest.UserAgent = "http_requester/0.1"
            hwrequest.Timeout = 5000
            hwrequest.Method = method
            If hwrequest.Method = "POST" Then
                hwrequest.ContentType = "application/x-www-form-urlencoded"
                Dim encoding As New Text.ASCIIEncoding() 'Use UTF8Encoding for XML requests
                Dim postByteArray() As Byte = encoding.GetBytes(POSTdata)
                hwrequest.ContentLength = postByteArray.Length
                Dim postStream As IO.Stream = hwrequest.GetRequestStream()
                postStream.Write(postByteArray, 0, postByteArray.Length)
                postStream.Close()
            End If
            Dim hwresponse As Net.HttpWebResponse = hwrequest.GetResponse()
            If hwresponse.StatusCode = Net.HttpStatusCode.OK Then
                Dim responseStream As IO.StreamReader = _
                  New IO.StreamReader(hwresponse.GetResponseStream())
                streamResponse = responseStream.ReadToEnd()
            End If
            hwresponse.Close()
        Catch e As Exception
            responseData = "An error occurred: " & e.Message
        End Try
        Return responseData
    End Function


What am I doing wrong here? How would I go about passing the file that was selected in the second textbox I created? Any help would be appriciated!
 
@jncilhinney - I took your advice and tried converting the sample you sent me and wasn't having much luck with it so I browsed around online some more..Is it true that the WebClient would be better for uploading a file but not for inputting other parameters, while httpwebrequest would be the other way around?

I've managed to put some code together myself but..When looking at the response it doesn't seam like the form is actually being submitted..H

Here is what I got so far

VB.NET:
    Private Sub SubmitThread_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles SubmitThread.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        For i As Integer = 0 To Me.lstSubmissionSites.CheckedItems.Count - 1
            r = i
            Dim selectedSite As String = String.Empty
            selectedSite = lstSubmissionSites.Items(i).ToString
            If lstSubmissionSites.InvokeRequired Then
                lstSubmissionSites.Invoke(Sub() lstSubmissionSites.SelectedIndex = r)
            End If

            If SubmitThread.CancellationPending = True Then
                e.Cancel = True
                Exit For
            Else
                Dim uri As String = selectedSite
                Dim myWebClient As New WebClient()

                Dim myNameValueCollection As New NameValueCollection()
                Dim title As String = postTitle
                Dim source As String = sourceUrl


                myNameValueCollection.Add("title", title)
                myNameValueCollection.Add("source", source)
                If ((OpenFileDialog1.FileName <> "") _
            AndAlso (Not (OpenFileDialog1.FileName) Is Nothing)) Then
                    myNameValueCollection.Add("picture", OpenFileDialog1.FileName)
                End If

                Dim responseArray As Byte() = myWebClient.UploadValues(uri, "POST", myNameValueCollection)
                test = (Encoding.ASCII.GetString(responseArray))
                worker.ReportProgress(0, test)
            End If
        Next
    End Sub

any ideas?
 
The WebClient actually uses a WebRequest internally. It provides a simple interface so it is easier to use in simple scenarios. The WebRequest provides more fine-grained control and is therefore required for more complex scenarios. If you were just uploading a single file then a WebClient would be a better option. For posting a virtual form, you must use a WebRequest.
 
Thanks for clearing that up. Since I'm looking to submit an actual web form here it appears HTTPWebRequest is the only route. I did find some more examples online and made some adjustments to fit my application. I'm connecting with the site but it still doesn't seam like the form is actually being submitted..When I look at the response I see no "success" or "unsuccessful" message in there..Looking at the content it looks like the form was not submitted.

Any chance you could have a quick look over my code and let me know if I'm missing something here? I'm converting the entire postData string which does have the file path in it..

VB.NET:
  Public Sub UploadFile(ByVal localFile As String)
        Dim Req As HttpWebRequest = DirectCast(WebRequest.Create(New Uri(uploadLink)), HttpWebRequest)
        Req.Method = "POST"
        Req.Referer = (uploadLink)
        Dim Boundary As String = "-------------------------" & DateTime.Now.Ticks.ToString
        Req.ContentType = "multipart/form-data; boundary=" & Boundary
        Dim NewLine As String = Environment.NewLine
        Dim PostData As String = NewLine & Boundary & NewLine
        PostData &= "Content-Disposition: form-data; title=" & postTitle & "; source=" & sourceUrl & "; picture=" & Chr(34) & IO.Path.GetFileName(localFile).ToString & Chr(34) & NewLine
        Select Case IO.Path.GetExtension(localFile).ToLower
            Case ".gif"
                PostData &= "Content-Type: image/gif" & NewLine
            Case ".jpg"
                PostData &= "Content-Type: image/jpeg" & NewLine
            Case ".png"
                PostData &= "Content-Type: image/png" & NewLine
        End Select
        Dim HeaderBytes() As Byte = System.Text.Encoding.UTF8.GetBytes(PostData)

        MsgBox(Boundary)
        MsgBox(PostData)

        Dim Bytes() As Byte = File.ReadAllBytes(localFile)
        Req.ContentLength = HeaderBytes.Length + Bytes.Length
        MsgBox("Content Length : " & Req.ContentLength)

        Dim RunningTotal As Integer = 0
        Using ReqStream As Stream = Req.GetRequestStream
            Using fs As New FileStream(localFile, FileMode.Open, FileAccess.Read)

                Dim Buffer(4096) As Byte
                Dim BytesRead As Integer = fs.Read(Buffer, 0, Buffer.Length)
                ReqStream.Write(HeaderBytes, 0, HeaderBytes.Length)

                While BytesRead > 0
                    RunningTotal += BytesRead
                    ReqStream.Write(Buffer, 0, BytesRead)
                    BytesRead = fs.Read(Buffer, 0, Buffer.Length)

                    'Console.SetCursorPosition(0, Console.CursorTop)
                    'Console.Write(RunningTotal & "/" & fs.Length)

                End While

            End Using

            ReqStream.Close()
        End Using
        Dim Res As HttpWebResponse = DirectCast(Req.GetResponse, HttpWebResponse)
        Dim Reader As New StreamReader(Res.GetResponseStream)
        Dim InformationA As String = String.Empty
        InformationA = Reader.ReadToEnd
        informationB = InformationA

    End Sub

Many thanks!
 
Back
Top