【问题标题】:ASP Classic, Download big files does not work on certain serversASP Classic,在某些服务器上无法下载大文件
【发布时间】:2021-01-27 14:50:26
【问题描述】:

我有以下脚本,在本地(Windows 10 IIS、Windows 2003 Server)上运行良好,但在我们的托管服务器(Windows 2003 Server)上运行良好。任何超过 4mb 的内容都会下载非常慢,然后在到达文件末尾之前超时。但是,在本地,它可以快速完整地下载。

直接下载(链接到文件本身)会在 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
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

【问题讨论】:

  • 可能是 IIS 配置问题。我相信默认设置是 4MB...
  • 如上所述。您可以直接下载文件,它会立即下载大文件。只是没有脚本。
  • 是页面中的所有代码还是sn-p?可能是其他原因导致速度变慢?或者如何增加块大小?例如,读取一个块 (2048 字节) 需要 100 毫秒,这意味着下载一个 4 MB 的文件大约需要 3 分钟,但是将块大小增加到 20480 ( 20 KB) 只需要大约。 20 秒,看出区别了吗?

标签: asp-classic


【解决方案1】:

基本上是由于脚本超时。在使用 IIS 10 升级到 Win 2016 后,我在 IIS 10 中遇到了同样的问题(默认超时时间更短)。

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

【讨论】:

【解决方案2】:

只看代码 sn-p 它似乎很好,这正是我用来下载大文件的方法(尤其是使用 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 页面的默认 scriptTimeout00:01:30,因此在上面的示例中,以 100 毫秒持续读取 2 KB 块的 4 MB 文件会在脚本完成之前超时。

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

所以只需尝试增加CHUNK

Const CHUNK = 20480 'Read in chunks of 20 KB

【讨论】:

  • 你摇滚。将 0 添加到末尾,完成了这项工作。我刚刚在托管服务器上测试了它,它以直接下载时间的 1/2 下载了 26mb 的文件,并且它完成了。 26mb 大约需要 10 秒。直接下载大约5秒。您认为添加另一个 0 (204800) 可以吗?
  • @WayneBarron 它需要一些试验和错误,我个人会以字节增量设置它,所以尝试了 2 KB、20 KB 所以接下来我会尝试 200 KB (204800字节)。只要不断增加,直到您对吞吐量感到满意。读取的块越大,需要的资源就越多,因此需要在资源使用和性能之间进行权衡。
  • 我将它设置为 2048000。这大约是每秒 1.5mb 的下载速度。所以,这应该处理得很好。感谢 Lankymart,祝你玩得开心。
【解决方案3】:

我的代码有点不同,使用 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

【讨论】:

  • 我过去使用Do While 进行这种类型的分块下载没有问题。
  • 这是个人喜好,但我发现Do 循环是一种更简洁的方法,然后有一个额外的位来读取剩余部分,也避免了Response.BinaryWrite() 上的代码重复。
  • 在我的情况下,正是读取的块大小导致了我的问题,正如上面 Lankymart 接受的答案中所指出的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
相关资源
最近更新 更多