Question Issue with FileLocation in a TextBox

digitaldrew

Well-known member
Joined
Nov 10, 2012
Messages
167
Programming Experience
Beginner
Hey everyone..I'm working to submit a mutlipart form using HTTPWebRequest and everything appears to be working - except for one part.

The program should be submitting 3 fields - a name, a source, and an image. I'm using openfiledialog to let the user select the image they want to submit and then setting that location into a textbox. Since the form I'm submitting to only uses the filename (not the entire location) I am splitting the file location path and only passing the actual filename (that ends with .jpg, .png, or .gif)

Here is the issue..When trying to submit the form I get an exception everytime. The exception is saying "Could not find file 'C:\Users\Drew\Documents\Visual Studio 2010\Projects\WindowsApplication1\WindowsApplication1\bin\Debug\Image.jpg'."

I can't figure out why it's looking into this visual studio debug folder when the file locaton specified in the textbox is C:\Users\Drew\Desktop\Image.jpg

Here is part of my code
VB.NET:
                Try
                    Dim strResponse As String
                    Dim cHTTP As New http

                    ' Set up POST data
                    Dim pdlPostData As New http.PostDataList  ' Form fields
                    pdlPostData.Add("title", txtPostTitle.Text)
                    pdlPostData.Add("source", txtSourceUrl.Text)
                    pdlPostData.Add("submit", "Submit")
                    Dim mpfPictureFile As New http.MultipartPostFile  ' File to upload
                    mpfPictureFile.Name = "foto"
                    Dim lines() As String = txtImage.Text.Split("\")
                    For Each line In lines
                        If line.Contains(".jpg") Or line.Contains(".gif") Or line.Contains(".png") Then
                            MsgBox(line)
                            mpfPictureFile.Path = line
                        End If
                    Next
                    mpfPictureFile.ContentType = "application/octet-stream"

                    ' Send request now
                    strResponse = cHTTP.PostMultipartRequest(selectedSite, pdlPostData, mpfPictureFile, selectedSite, , , "text/html", , , True)

                    ' Determine success
                    If InStr(strResponse, "Image sent!") > 0 Then
                        ' Picture submitted
                        informationB = "Picture successfully submitted!"
                    Else
                        ' Failed to submit picture
                        informationB = "Failed to submit picture!"
                    End If
                Catch ex As Exception
                    MsgBox(ex.Message)
                    If lstWlol.InvokeRequired Then
                        lstWlol.Invoke(Sub() lstWlol.SetItemChecked(r, False))
                        lblUnsuccessful.Invoke(Sub() lblUnsuccessful.Text = lblUnsuccessful.Text + 1)
                        txtLog.Invoke(Sub() txtLog.AppendText("Website Gave an Error and Has Been Unchecked" & vbCrLf))
                    End If
                    Continue For
                End Try

What could I be doing wrong here? as you see I have MsgBox(line) directly under my split and that messagebox shows the appropriate filename that should be getting passed (Image.jpg)..but yet it still catches the exception everything??
 
Hi,

The issue is that you are removing the directory structure to the file location by using the split command. On the basis that you have removed the files location, i.e, " C:\Users\Drew\Desktop\" your project is trying the find the file in your projects current runtime directory, being "C:\Users\Drew\Documents\Visual Studio 2010\Projects\WindowsApplication1\WindowsApplicati on1\bin\Debug\"

Here is a quick example showing the same error using a PictureBox:-

VB.NET:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
  Dim strFileName As String = "d:\temp\Bee.png"
  Dim lines() As String = strFileName.Split("\"c)
 
  For Each line In lines
    If line.Contains(".jpg") Or line.Contains(".gif") Or line.Contains(".png") Then
      'you will see that this does not work
      PictureBox1.Image = Image.FromFile(line)
      'However this will work since I have used the original file name
      'which still contains the directory structure
      PictureBox1.Image = Image.FromFile(strFileName)
    End If
  Next
End Sub

The simple solution is to not split the directory structure from the file name.

Hope that helps.

Cheers,

Ian
 
Hey Ian, thanks for your response. Since I need to store mpfPictureFile.Path as only the "Image.Extension" what would be the best way to do it aside from a split?
 
Hi,

I am not really sure I can help you anymore since I cannot find any reference to http.MultipartPostFile on MSDN so I am guessing that this is a sub class of your own making?

That said, and after quickly looking at this again, are you sure you are doing things right? The reason I ask is as follows:-

1) mpfPictureFile.Path = line, implies that a Path to the file should be set and not a filename?

2) mpfPictureFile.Name = "foto", implies that this should be the name of your image and yet this is just a literal?

3) Your comment, "I need to store mpfPictureFile.Path as only the "Image.Extension"" does not sound right based on the description of the property you are trying to set and nor do you assign the image extension anywhere in your current code example.

Hope that helps.

Cheers,

Ian
 
Hey Ian, you are correct - http.MultipartPostFile is another class I have added to the project. I have two different types of websites I am submitting to. The only difference between the forms on each of these two sites is A) the class name for the photo box inside the form and B) on one website the photo box inside the form displays the entire path while the other form only displays the filename once you have browsed and selected the image to upload. I have been trying to use the same class to work with both sites..the one I am displaying here is the second one where you can tell I'm trying to use that same value but just split off the information I don't need.

foto is actually the class name for the box located on the form I am trying to submit.

Here is the code for http.MultipartPostFile

VB.NET:
Public Function PostMultipartRequest(ByVal strURL As String,
                                         ByVal pdlPostData As PostDataList,
                                         ByVal mpfPostFile As MultipartPostFile,
                                         Optional ByVal strReferer As String = "",
                                         Optional ByVal strCookie As String = "",
                                         Optional ByVal strAccept As String = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
                                         Optional ByVal strEncodingType As String = "gzip,deflate",
                                         Optional ByVal strProxyHost As String = "",
                                         Optional ByVal intProxyPort As Integer = 0,
                                         Optional ByVal bReturnHeader As Boolean = False) As String

        ' Create new HttpWebRequest/Response instances
        Dim Request As HttpWebRequest
        Dim strBoundaryValue As String = DateTime.Now.Ticks.ToString("x")
        Dim strBoundary As String = "----" & strBoundaryValue
        Dim Response As HttpWebResponse
        Dim ResponseData As String
        Try
            Request = WebRequest.Create(strURL)
        Catch ex As Exception
            MsgBox("Failed to initialize WebRequest: " & ex.ToString, vbCritical, "http.PostMultipartRequest")
            Return ""
        End Try

        ' Configure the HttpWebRequest instance, including request headers
        Request.Method = "POST"
        Request.ProtocolVersion = New System.Version(1, 1)
        Request.UserAgent = strUserAgent
        Request.Accept = strAccept
        Request.Timeout = 60000
        Request.KeepAlive = True
        Request.Headers.Add(HttpRequestHeader.KeepAlive, "300")
        Request.Headers.Add(HttpRequestHeader.AcceptEncoding, strEncodingType)
        If strReferer <> "" Then Request.Referer = strReferer
        If strCookie = "" Then Request.CookieContainer = ccCookies Else Request.Headers.Add(HttpRequestHeader.Cookie, strCookie)
        Request.ContentType = "multipart/form-data; boundary=" & strBoundary

        ' Set proxy if one was passed
        If strProxyHost <> "" And intProxyPort <> 0 Then
            Request.Proxy = New Net.WebProxy(strProxyHost, intProxyPort)
        End If

        ' Prepare the POST data header chunk now
        Dim strBuilder As New StringBuilder()

        ' Add all of the data in pdlPostData
        For n As Integer = 0 To pdlPostData.Count - 1
            Dim PDI As PostDataList.PostDataItem = pdlPostData.GetItemByIndex(n)
            strBuilder.Append("--" & strBoundary)
            strBuilder.Append(vbCrLf)
            strBuilder.Append("Content-Disposition: form-data; name=""" & PDI.Name & """")
            strBuilder.Append(vbCrLf)
            strBuilder.Append(vbCrLf)
            strBuilder.Append(PDI.Value)
            strBuilder.Append(vbCrLf)
        Next

        ' Add the post file header chunk now (all of the post data minus the file bytes)
        strBuilder.Append("--" & strBoundary)
        strBuilder.Append(vbCrLf)
        strBuilder.Append("Content-Disposition: form-data; name=""" & mpfPostFile.Name & """; filename=""" & Path.GetFileName(mpfPostFile.Path) & """")
        strBuilder.Append(vbCrLf)
        strBuilder.Append("Content-Type: " & mpfPostFile.ContentType)
        strBuilder.Append(vbCrLf)
        strBuilder.Append(vbCrLf)

        ' Create byte arrays for the POST data chunks
        Dim bPOSTHeaderChunk() As Byte = System.Text.Encoding.UTF8.GetBytes(strBuilder.ToString)                            ' Contains all of the POST data, up to the file's contents
        Dim bPOSTFileChunk() As Byte = My.Computer.FileSystem.ReadAllBytes(mpfPostFile.Path)                                ' Contains the contents of the file included in the POST data
        Dim bPOSTEndBoundary() As Byte = System.Text.Encoding.ASCII.GetBytes(vbCrLf & "--" & strBoundary & "--" & vbCrLf)   ' Contains the ending boundary

        ' Update class string so the POST data can be displayed in UI
        sPostData = strBuilder.ToString & "{{FILE BYTES HERE}}" & vbCrLf & strBoundary & "--" & vbCrLf

        ' Set the request's content length, based on the chunk sizes
        Request.ContentLength = bPOSTHeaderChunk.Length + bPOSTFileChunk.Length + bPOSTEndBoundary.Length

        ' Perform request now
        Dim sRequestStream As Stream
        Try
            ' Get the request stream
            sRequestStream = Request.GetRequestStream()
            ' Send the POST chunks now; header -> file -> end boundary
            sRequestStream.Write(bPOSTHeaderChunk, 0, bPOSTHeaderChunk.Length)
            sRequestStream.Write(bPOSTFileChunk, 0, bPOSTFileChunk.Length)
            sRequestStream.Write(bPOSTEndBoundary, 0, bPOSTEndBoundary.Length)
        Catch Ex As Exception
            MsgBox("Request stream failed: " & Ex.ToString, vbCritical, "http.PostMultipartRequest")
            Return ""
        End Try

        ' Close writer stream
        sRequestStream.Close()

        ' Receive Response
        Dim SR As StreamReader
        Try
            Response = Request.GetResponse()
            SR = New StreamReader(Response.GetResponseStream())
            ResponseData = SR.ReadToEnd()
        Catch ex As Exception
            MsgBox("Response stream failed: " & ex.ToString, vbCritical, "http.PostMultipartRequest")
            Return ""
        End Try

        ' Handle cookies
        ccCookies.Add(Response.Cookies)

        ' Add header to response string if needed
        If bReturnHeader = True Then ResponseData = Response.Headers.ToString & ResponseData

        ' Close reader stream
        SR.Dispose()

        ' Return HTTP response string
        Return ResponseData

    End Function
 
Hi,

Its never going to work if I am understanding what you are trying to do. If you pass just a filename to your function through your mpfPictureFile variable then these points in your function are never going to work:-

VB.NET:
Path.GetFileName(mpfPostFile.Path)
This returns a filename from a fully qualified path so will never work.

VB.NET:
Dim bPOSTFileChunk() As Byte = My.Computer.FileSystem.ReadAllBytes(mpfPostFile.Path)
This is reading a file from a fully qualified path so will never work.

If you want this class to be multifunctional then you are going to have to rethink the design of this function.

Hope that helps.

Cheers,

Ian
 
Thanks for the input Ian. What I've done is copied the entire class over to a second class..I'll mess around with it more now and test it out without disrupting other list which properly submits as of right now.
 
Good Idea. Once you have got the second class working, that's the point when you can start thinking about merging the two classes to become a single multifunctional class.

Good Luck.

Ian
 
Back
Top