在多个块中下载文件
本文关键字:下载 文件 | 更新日期: 2023-09-27 18:21:28
我正在编写一段代码,该代码应该下载1MB块中的单个文件。我使用了与这个问题中相同的代码:在C#中下载大块的大文件,并将其转换为VB.NET.
与上一个问题相同的代码运行良好,并将文件写入磁盘。但第二个web请求中似乎出现了问题。为了测试,我从https://d13yacurqjgara.cloudfront.net/users/22/screenshots/631004/attachments/53012/wallpaper-retina-cinemadisplay.png使用下面的VB.NET代码。
下载的PNG似乎已经完成了一半,剩下的图像被打乱了。
我将defaultSize
和chunk
增加到10MB,文件下载非常完美,但For/Next循环中似乎有什么东西截断或污染了数据。
有什么想法可能导致这种情况发生吗?
Private Const defaultSize As Long = 1048576
Private chunk As Long = 1048576
Private offset As Long = 0
Private Function downloadFile(ByVal url As String, ByVal filename As String) As Boolean
Dim size As Long = getSize(url)
Dim blockSize As Integer = Convert.ToInt32(size / defaultSize)
Dim remainder As Integer = Convert.ToInt32(size Mod defaultSize)
If remainder > 0 Then
blockSize += 1
End If
Dim fileStream As FileStream = File.Create("C:'mydirectory'" & filename)
For i As Integer = 0 To blockSize - 1
If i = blockSize - 1 Then
chunk = remainder
End If
Dim req As HttpWebRequest = HttpWebRequest.Create(url)
req.Method = WebRequestMethods.Http.Get
req.AddRange(Convert.ToInt32(offset), Convert.ToInt32(chunk + offset))
Dim resp As HttpWebResponse = req.GetResponse()
Using respStream As Stream = resp.GetResponseStream
Dim buffer(4096) As Byte
Dim bytesRead As Integer
Do
bytesRead = respStream.Read(buffer, 0, 4096)
If bytesRead > 0 Then fileStream.Write(buffer, 0, bytesRead)
Loop While bytesRead > 0
End Using
offset += chunk
resp.Close()
resp.Dispose()
Next
fileStream.Close()
Return True
End Function
Private Function getSize(ByVal url As String) As Long
Dim req As WebRequest = WebRequest.Create(url)
req.Method = WebRequestMethods.Http.Head
Dim resp As WebResponse = req.GetResponse
Return Long.Parse(resp.ContentLength)
End Function
除了整理一些代码(我想你无论如何都会这样做,因为你是从C#转换过来的),做一个小的更改就能完美地工作。
线路
offset += chunk
应该是
offset += chunk + 1
这解决了问题,因为offset
从0开始,并且在下一个循环中添加块大小,因此添加了一个兆字节并从那里开始。您希望从最后一个兆字节之后的字节继续!我确实开始解释它是如何工作的,但我想出的例子不起作用。。。所以我无法解释!也许其他人可以;这与req.AddRange
有关——您指定的是一个范围,而不是总数。
关于代码转换的一个问题。
Convert.ToInt32(size / defaultSize)
这是相同的代码,在C#代码和VB中忽略分号。然而,它没有考虑到在两种语言中,"/"运算符可以通过整数除法返回不同的值这一细微差别。
变量Size和defaultSize都是长整数。当在C#中对两个整数进行除法时,结果是一个整数,小数被截断而不取整。在VB中,将两个整数除法,结果被强制为十进制,然后四舍五入。
/操作员(C#参考)
/操作员(VB参考)
例如,如果size和defaultSize的值分别为68和10。
VB
Dim result As Integer = Convert.ToInt32(size / defaultSize) 'VB result 7
C#
int result = Convert.ToInt32(size / defaultSize); // C# result 6
这可能会对我没有追求的算法产生怎样的影响,因为最初的代码被声称仍然不起作用。