Question

I am getting the following exception thrown when using the function below to upload a video file to my web server. I am using this function as I need the memory usage to be low as the video files being uploaded are in excess of 150MB.

The error that is being thrown is: You must write ContentLength bytes to the request stream before calling [Begin]GetResponse.

I have looked over the code a few times now & simply cannot seem to notice where I am going wrong & likely just need a second set of eyes to find my mistake!

Function:

Friend Function LowMemoryUploader(ByVal FilePath As String) As String
        ServicePointManager.ServerCertificateValidationCallback = (Function(sender, certificate, chain, sslPolicyErrors) True)
        Dim oUri As New Uri("http://mysite.com/upload.php")
        Dim NowTime As String = DateTime.Now.Ticks.ToString().Substring(0, 14)
        Dim strBoundary As String = "-----------------------------" & NowTime
        ' Set Filename
        Dim FileName As String = FilePath.Split(CChar("\")).Last()
        ' The trailing boundary string
        Dim boundaryBytes As Byte() = Encoding.ASCII.GetBytes(vbCr & vbLf & "--" & strBoundary & vbCr & vbLf)
        ' The post message header
        Dim sb As New StringBuilder()
        ' Add Variables
        sb.Append(strBoundary & vbCrLf & "Content-Disposition: form-data; name=""upload""" & vbCrLf & vbCrLf & "1" & vbCrLf)
        sb.Append(strBoundary & vbCrLf & "Content-Disposition: form-data; name=""upload_file""; filename=""" & FileName & """" & vbCrLf)
        sb.Append("Content-Type: video/" & FilePath.Split(".").Last())
        sb.Append(vbCrLf & vbCrLf)
        ' Set Header Bytes
        Dim strPostHeader As String = sb.ToString()
        Dim postHeaderBytes As Byte() = Encoding.UTF8.GetBytes(strPostHeader)
        ' The WebRequest
        Dim oWebrequest As HttpWebRequest = DirectCast(WebRequest.Create(oUri), HttpWebRequest)
        ' Set Request Settings
        System.Net.ServicePointManager.Expect100Continue = False
        oWebrequest.Method = "POST"
        oWebrequest.UserAgent = Useragent
        oWebrequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
        oWebrequest.ContentType = "multipart/form-data; boundary=---------------------------" & NowTime
        oWebrequest.AllowAutoRedirect = True
        oWebrequest.Timeout = 600000
        oWebrequest.CookieContainer = cookies
        ' This is important, otherwise the whole file will be read to memory anyway...
        oWebrequest.AllowWriteStreamBuffering = False
        ' Get a FileStream and set the final properties of the WebRequest
        Dim oFileStream As New FileStream(FilePath, FileMode.Open, FileAccess.Read)
        Dim length As Long = postHeaderBytes.Length + oFileStream.Length + boundaryBytes.Length
        oWebrequest.ContentLength = length
        Dim oRequestStream As Stream = oWebrequest.GetRequestStream()
        ' Write the post header
        oRequestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length)
        ' Stream the file contents in small pieces (4096 bytes, max).
        Dim buffer As Byte() = New Byte(1096) {}
        Dim bytesRead As Integer = oFileStream.Read(buffer, 0, buffer.Length)
        While bytesRead <> 0
            bytesRead = oFileStream.Read(buffer, 0, buffer.Length)
            oRequestStream.Write(buffer, 0, bytesRead)
        End While
        oFileStream.Close()
        ' Add the trailing boundary
        oRequestStream.Write(boundaryBytes, 0, boundaryBytes.Length)
        Dim oWResponse As WebResponse = oWebrequest.GetResponse()
        Dim s As Stream = oWResponse.GetResponseStream()
        Dim sr As New StreamReader(s)
        Dim sReturnString As String = sr.ReadToEnd()
        ' Clean up
        oRequestStream.Close()
        s.Close()
        sr.Close()
        Return sReturnString
    End Function
Was it helpful?

Solution

This part doesn't look right:

Dim bytesRead As Integer = oFileStream.Read(buffer, 0, buffer.Length)
While bytesRead <> 0
    bytesRead = oFileStream.Read(buffer, 0, buffer.Length)
    oRequestStream.Write(buffer, 0, bytesRead)
End While

Note that Dim bytesRead As Integer = oFileStream.Read(buffer, 0, buffer.Length) does an initial read, but it gets immediately overwritten within your loop. Therefore you are writing one less block to the oRequestStream than you read.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top