After something thinking, I figured that I needed to post a multi-part form.
I refactored my code and added the missing logic. Here is the result:
Public Shared Function RemoteFileUpload(ByVal url As String, ByRef file As
Web.HttpPostedFile, ByVal elements As NameValueCollection) As String
Dim boundary As String = "----------------------------" &
DateTime.Now.Ticks.ToString("x")
Dim boundarybytes As Byte() = System.Text.Encoding.ASCII.GetBytes(vbCr &
vbLf & "--" & boundary & vbCr & vbLf)
Dim memStream As Stream = New System.IO.MemoryStream()
Try
'
'add form elements to stream
'
'fields are a sequence of (name, value) elements for regular form fields.
Dim formdataTemplate As String = vbCr & vbLf & "--" & boundary & vbCr & vbLf
& "Content-Disposition: form-data; name=""{0}"";" & vbCr & vbLf & vbCr &
vbLf & "{1}"
For Each key As String In elements.Keys
Dim formitem As String = String.Format(formdataTemplate, key, elements(key))
Dim formitembytes As Byte() = System.Text.Encoding.UTF8.GetBytes(formitem)
memStream.Write(formitembytes, 0, formitembytes.Length)
Next
'delimiter
memStream.Write(boundarybytes, 0, boundarybytes.Length)
'
'add file's metadata to stream
'
Dim header As String, headerData As Byte()
'file's content disposition
Const CONTENT_DISPOSITION = "Content-Disposition: form-data; name=""{0}"";
filename=""{1}""" & vbCr & vbLf
header = String.Format(CONTENT_DISPOSITION, "fileupload", file.FileName)
headerData = System.Text.Encoding.UTF8.GetBytes(header)
memStream.Write(headerData, 0, headerData.Length)
'file's content type
'extra CR LF as it is the last header
Const CONTENT_TYPE As String = " Content-Type: {0}" & vbCr & vbLf & vbCr &
vbLf
header = String.Format(CONTENT_TYPE, file.ContentType)
headerData = System.Text.Encoding.UTF8.GetBytes(header)
memStream.Write(headerData, 0, headerData.Length)
'
'add file to stream
'
'convert stream to byte()
Dim buffer As Byte() = New Byte(file.InputStream.Length - 1) {}
file.InputStream.Position = 0
file.InputStream.Read(buffer, 0, buffer.Length)
file.InputStream.Close()
'write file's bytes
memStream.Write(buffer, 0, buffer.Length)
'delimiter
memStream.Write(boundarybytes, 0, boundarybytes.Length)
'convert stream to byte()
ReDim buffer(memStream.Length - 1)
memStream.Position = 0
memStream.Read(buffer, 0, buffer.Length)
memStream.Close()
'open connection to server
Dim WebRequest As HttpWebRequest = DirectCast(HttpWebRequest.Create(url),
HttpWebRequest)
With WebRequest
..ContentType = "multipart/form-data; boundary=" & boundary
..Method = "POST"
..KeepAlive = True
..Credentials = System.Net.CredentialCache.DefaultCredentials
..ContentLength = buffer.Length
End With
'POST form and file's bytes
Using requestStream As System.IO.Stream = WebRequest.GetRequestStream()
requestStream.Write(buffer, 0, buffer.Length)
End Using
Dim html As String = String.Empty
'get response from posting
Using WebResponse As HttpWebResponse = CType(WebRequest.GetResponse,
HttpWebResponse)
With WebResponse
Select Case .StatusCode
Case HttpStatusCode.OK
Using responseStream As System.IO.Stream = .GetResponseStream
Using sr As New System.IO.StreamReader(responseStream, Encoding.UTF8, True)
html = sr.ReadToEnd
End Using
End Using
Case Else
'TODO: error handling
End Select
End With
End Using
Return html
Catch ex As Exception
Throw
Finally
memStream.Dispose()
End Try
End Function