我正在使用发送HTTP请求并获得各自答案的Sharefile API。它们是通过URL制作的,并始终使用相同的功能。在这里。
Private Function InvokeShareFileOperation(ByVal requestUrl As String) As JObject
Dim request As HttpWebRequest = WebRequest.Create(requestUrl)
Dim response As HttpWebResponse = request.GetResponse()
Dim reader As StreamReader = New StreamReader(response.GetResponseStream())
Dim json As String = reader.ReadToEnd()
response.Close()
Return JObject.Parse(json)
End Function
由于某些操作有点长,我需要以某种方式跟踪他们正在进行的进度并且不知道如何操作。后来我打算使用这个进度并从中创建一个进度条。
(编辑) 顺便说一句,它是占用大部分时间的第二个代码行(下面),即跟踪操作。
Dim response As HttpWebResponse = request.GetResponse()
答案 0 :(得分:4)
编辑:我认为您无法以任何准确的方式衡量进度,因为大部分操作似乎依赖于处理请求的远程服务器。 GetResponse()处理设置DNS,连接,发送和等待远程服务器,这完全不在您手中。只有返回内容长度标头,才能读取响应流。我个人最初会将进度显示为20%,GetResponse返回时显示为60%,如果您在下载前有内容长度,则可以逐步显示最后40%,或者在读完响应流后一次性完成。< / p>
作为Web请求,您可以先查找内容长度,然后使用缓冲区而不是ReadToEnd()读取响应流。这允许您在下载响应时计算进度并触发通知。
Dim request As HttpWebRequest = WebRequest.Create(requestUrl)
Using response As HttpWebResponse = request.GetResponse()
Dim contentLength As Long = response.ContentLength
Dim bytesReceived As Long
Dim bufferLength as Integer = 8192
Dim buffer(bufferLength) As Char
Dim sb As New StringBuilder
Using reader As StreamReader = New StreamReader(response.GetResponseStream())
Do
Dim bufferedCount As Integer = reader.Read(buffer, 0, bufferLength)
sb.Append(buffer, 0, bufferedCount)
bytesReceived += bufferedCount
Console.WriteLine(bytesReceived / contentLength * 100 & "%")
Loop While bytesReceived < contentLength
End Using
Return JObject.Parse(sb.ToString)
End Using
显然,您可以将Console.WriteLine替换为进度更新功能或调用SignalR中心来更新网页,您可以尝试使用缓冲区大小来查看哪种方式最适合您。
答案 1 :(得分:3)
首先,我们必须找出什么在放缓。在调用GetResponse()
之前不会发送请求,因此服务器处理可能需要一些时间。下载也需要一些时间。如果响应很小(相对于连接速度),你不能做太多(如果服务器是你的,你可以,但我们将专注于客户端),因为你无法从服务器获得进展。如果响应很大,并且您想跟踪下载,则只有拥有Content-Length
标题才能执行此操作。要获得只有标头,服务器必须支持HEAD
请求方法。所以这是代码:
Imports System
Imports System.Net
Imports System.IO
Imports System.Text
Imports System.Threading
Imports Microsoft.VisualBasic
Public Class Form1
Private Function InvokeShareFileOperation(ByVal requestUrl As String) As JObject
HTTPWebRequest_GetResponse.Main(requestUrl)
ProgressBar1.Value = 0
Dim result As String
Do
Try
ProgressBar1.Value = HTTPWebRequest_GetResponse.progress
Catch ex As ArgumentOutOfRangeException
ProgressBar1.Style = ProgressBarStyle.Marquee
End Try
If HTTPWebRequest_GetResponse.done = True Then
result = HTTPWebRequest_GetResponse.response
ProgressBar1.Style = ProgressBarStyle.Continuous
ProgressBar1.Value=100
Debug.WriteLine(result)
Return JObject.Parse(result)
Exit Do
End If
Loop
End Function
End Class
Public Class RequestState
' This class stores the State of the request.
Private BUFFER_SIZE As Integer = 1024
Public requestData As StringBuilder
Public BufferRead() As Byte
Public request As HttpWebRequest
Public response As HttpWebResponse
Public streamResponse As Stream
Public Sub New()
BufferRead = New Byte(BUFFER_SIZE) {}
requestData = New StringBuilder("")
request = Nothing
streamResponse = Nothing
End Sub 'New
End Class 'RequestState
Class HTTPWebRequest_GetResponse
Private BUFFER_SIZE As Integer = 1024
Public Shared response As String
Public Shared done As Boolean = False
Public Shared length As Long = 1
Public Shared progress As Integer
Public Shared myHttpWebRequest As HttpWebRequest
Public Shared myRequestState As New RequestState()
Shared Sub Main(url As String)
Try
Dim headRequest As HttpWebRequest = WebRequest.Create(url)
headRequest.Method = "HEAD"
Dim headResponse As HttpWebResponse = headRequest.GetResponse
length = headResponse.ContentLength
Debug.WriteLine(length)
headResponse.Close()
' Create a HttpWebrequest object to the desired URL.
myHttpWebRequest = WebRequest.Create(url)
' Create an instance of the RequestState and assign the previous myHttpWebRequest
' object to its request field.
myRequestState.request = myHttpWebRequest
'Dim myResponse As New HTTPWebRequest_GetResponse()
' Start the asynchronous request.
Dim result As IAsyncResult = CType(myHttpWebRequest.BeginGetResponse(New AsyncCallback(AddressOf RespCallback), myRequestState), IAsyncResult)
Catch e As WebException
Debug.WriteLine("Main Exception raised!")
Debug.WriteLine("Message: " + e.Message)
Debug.WriteLine("Status: " + e.Status)
Catch e As Exception
Debug.WriteLine("Main Exception raised!")
Debug.WriteLine("Source : " + e.Source)
Debug.WriteLine("Message : " + e.Message)
End Try
End Sub 'Main
Private Shared Sub RespCallback(asynchronousResult As IAsyncResult)
Debug.WriteLine("RespCallBack entered")
Try
' State of request is asynchronous.
Dim myRequestState As RequestState = CType(asynchronousResult.AsyncState, RequestState)
Dim myHttpWebRequest As HttpWebRequest = myRequestState.request
myRequestState.response = CType(myHttpWebRequest.EndGetResponse(asynchronousResult), HttpWebResponse)
' Read the response into a Stream object.
Dim responseStream As Stream = myRequestState.response.GetResponseStream()
myRequestState.streamResponse = responseStream
' Begin the Reading of the contents of the HTML page.
Dim asynchronousInputRead As IAsyncResult = responseStream.BeginRead(myRequestState.BufferRead, 0, 1024, New AsyncCallback(AddressOf ReadCallBack), myRequestState)
Return
Catch e As WebException
Debug.WriteLine("RespCallback Exception raised!")
Debug.WriteLine("Message: " + e.Message)
Debug.WriteLine("Status: " + e.Status)
Catch e As Exception
Debug.WriteLine("RespCallback Exception raised!")
Debug.WriteLine("Source : " + e.Source)
Debug.WriteLine("Message : " + e.Message)
End Try
End Sub 'RespCallback
Private Shared Sub ReadCallBack(asyncResult As IAsyncResult)
Debug.WriteLine("ReadCallBack entered")
Try
Dim myRequestState As RequestState = CType(asyncResult.AsyncState, RequestState)
Dim responseStream As Stream = myRequestState.streamResponse
Dim read As Integer = responseStream.EndRead(asyncResult)
' Read the HTML page.
If read > 0 Then
myRequestState.requestData.Append(Encoding.ASCII.GetString(myRequestState.BufferRead, 0, read))
If length = -1 Or length = 0 Then
progress = -1
Else
progress = myRequestState.BufferRead.Length * 100 / length
Debug.WriteLine(progress)
End If
Dim asynchronousResult As IAsyncResult = responseStream.BeginRead(myRequestState.BufferRead, 0, 1024, New AsyncCallback(AddressOf ReadCallBack), myRequestState)
Else
If myRequestState.BufferRead.Length > 1 Then
Dim fullResponse As String = myRequestState.requestData.ToString
response = fullResponse.Substring(0, fullResponse.IndexOf("</body>")).Substring(fullResponse.IndexOf(">", fullResponse.IndexOf("<body")) + 2) 'Returns only body
' Release the HttpWebResponse resource.
myRequestState.response.Close()
done = True
Debug.WriteLine(done)
End If
responseStream.Close()
End If
Catch e As WebException
Debug.WriteLine("ReadCallBack Exception raised!")
Debug.WriteLine("Message: " + e.Message)
Debug.WriteLine("Status: " + e.Status)
Catch e As Exception
Debug.WriteLine("ReadCallBack Exception raised!")
Debug.WriteLine("Source : " + e.Source)
Debug.WriteLine("Message : " + e.Message)
End Try
End Sub 'ReadCallBack
End Class 'HttpWebRequest_BeginGetResponse
我从http://msdn.microsoft.com/en-us/library/debx8sh9(v=vs.110).aspx获取代码并更改了它。
编辑:代码现在只返回正文,响应已关闭。
EDIT2:正如@ Geezer68所说,它不是100%准确,但可以向用户显示进度。
答案 2 :(得分:2)
我很确定你想要的是reader.BaseStream.Length
所以你可以在阅读之前知道它的长度。 (至少我这样做了,所以我试过了)但是它向NotSupportedException
投了This stream does not support seek operations
消息。所以我用Google搜索StreamReader + This stream...
并找到了这个SO链接:
Error “This stream does not support seek operations” in C#
所以简短的回答是:这是不可能的。
答案 3 :(得分:1)
也许一个简单的秒表是一种开始的方式?
Dim timer As System.Diagnostics.Stopwatch = New Stopwatch()
Dim request As HttpWebRequest = WebRequest.Create(requestUrl)
timer.Start()
Dim response As HttpWebResponse = request.GetResponse()
timer.Stop()
Dim reader As StreamReader = New StreamReader(response.GetResponseStream())
Dim json As String = reader.ReadToEnd()
response.Close()
Label1.Text = "Secs:" & timer.Elapsed.ToString()
答案 4 :(得分:0)
这是Microsoft示例的链接 在此处设置缓冲区大小并在响应对象上回调 https://msdn.microsoft.com/en-us/library/86wf6409%28v=vs.110%29.aspx