ASP经典,下载大文件无法在某些服务器上工作

ASP经典,下载大文件无法在某些服务器上工作

问题描述:

我有以下脚本,它适用于本地(Windows 10 IIS,Windows 2003 Server),但不在我们的托管服务器(Windows 2003 Server)上。任何超过4MB的文件都会下载得非常慢,然后在文件结束之前超时。但是,在本地,它快速且完整地下载。ASP经典,下载大文件无法在某些服务器上工作

做一个直接下载(链接到文件本身)从我们的托管服务提供商服务器在5秒内下载一个26.5mb文件。所以,下载限制没有问题。它似乎有一个问题,与托管服务器和此脚本。有任何想法吗?

Response.AddHeader "content-disposition","filename=" & strfileName 
Response.ContentType = "application/x-zip-compressed" 'here your content -type 

Dim strFilePath, lSize, lBlocks 
'Const CHUNK = 2048 
' Thanks to Lankymart. I have set this and it download at 1.5MB a second, so that is running pretty well for what I need it to be. 
Const CHUNK = 2048000 
set objStream = CreateObject("ADODB.Stream") 
objStream.Open 
objStream.Type = 1 
objStream.LoadFromfile Server.MapPath("up/"&strfileName&"") 
lSize = objStream.Size 
Response.AddHeader "Content-Size", lSize 
lBlocks = 1 
Response.Buffer = False 
Do Until objStream.EOS Or Not Response.IsClientConnected 
Response.BinaryWrite(objStream.Read(CHUNK)) 
Loop 

objStream.Close 
+0

大概IIS配置问题。我相信默认设置是4MB ... – sgeddes

+0

如上所述。您可以直接下载文件,并立即下载大文件。只是不与脚本。 –

+0

是页面中的所有代码还是代码片段?也许是别的原因导致了减速?或者增加块大小呢?举例来说,读取一个块*(2048字节)*需要100毫秒,这意味着一个4 MB的文件需要大约3分钟的下载量,但是增加块大小来说20480 *(20 KB)*只会花费约。 20秒,看到区别? – Lankymart

只看代码片段看起来是罚款,是非常的方法,我会用下载大文件(尤其喜欢使用Response.IsClientConnected

然而,尽管如此,它可能会根据文件的大小读取块的大小。

非常粗略的公式是这样的......

time to read = ((file size/chunk size) * read time) 

因此,如果我们使用一个4 MB文件的例子(4194304字节)说需要100毫秒来读取每个数据块,然后以下适用;的2048个字节(2 KB)

  • 块大小将取约3分钟阅读。

  • 块大小为20480字节(20 KB)将需要约。 20秒钟才能阅读。在IIS 7

经典的ASP页面和上面有一个默认的00:01:30scriptTimeout所以在上面在2 KB块100毫秒不断阅读会超时的脚本可以完成前4 MB的文件的例子。

现在,这些只是粗略统计你的阅读时间不会一直保持不变,它可能会更快,然后100毫秒(取决于磁盘读取速度)但我认为你明白了。

所以,只要尝试增加CHUNK

Const CHUNK = 20480 'Read in chunks of 20 KB 
+0

你摇滚。 将0添加到最后,完成了这项工作。 我刚刚在托管服务器上测试过它,它在直接下载的1/2时间内下载了26mb文件,并完成了它。约26秒26秒。 直接下载需要5秒钟。 你认为增加另一个0(204800)可以吗? –

+0

@WayneBarron它需要一些试验和错误,我个人会以字节为增量进行设置,所以尝试了2 KB,20 KB,然后尝试200 KB *(204800字节)*。只要继续增加,直到你对吞吐量满意为止。读取的块越大,需要的资源就越多,因此这是资源使用和性能之间的折衷。 – Lankymart

+0

我将它设置为2048000.这是以每秒1.5mb的下载速度拉动。所以,这应该处理得很好。谢谢Lankymart,有一个好的。 –

我所拥有的代码有点不同,使用For..Next循环代替Do..Until循环。不是100%确定这会真的在你的情况下工作,但值得一试。这里是我的代码版本:

For i = 1 To iSz/chunkSize 
    If Not Response.IsClientConnected Then Exit For 
    Response.BinaryWrite objStream.Read(chunkSize) 
Next 
If iSz Mod chunkSize > 0 Then 
    If Response.IsClientConnected Then 
     Response.BinaryWrite objStream.Read(iSz Mod chunkSize) 
    End If 
End If 
+0

我在过去没有问题的情况下对这种类型的分块下载使用了'Do While'。 – Lankymart

+1

这是个人偏好,但我发现一个'Do'循环是一个更清洁的方法,然后有额外的一点来读取其余部分,也避免了'Response.BinaryWrite()'上的代码重复。 – Lankymart

+0

就我而言,正如读者在Lankymart接受的答案中指出的那样,正在读取的是块的大小,这正在引起我的问​​题。 –

基本上是由于脚本超时。使用IIS 10升级到Win 2016后,我在IIS 10中的1GB文件遇到同样的问题(默认情况下,默认的超时时间较短)。

我使用块256000Server.ScriptTimeout = 60 0 '10分钟