寻求支持超2GB大文件分块下载的ASP/ASP.NET解决方案
大文件下载失败:Classic ASP/IIS无法处理2GB+文件
环境配置
- ESXi 6.5
- Windows 2016 Datacenter
- ARR Web Farm(临时配置:1台8GB内存ARR服务器 + 1台8GB内存Web服务器,经测试直接连Web服务器或通过ARR下载结果一致)
问题描述
无法从IIS 10服务器下载2GB以上的文件,目前只能将文件分割为1GB分块提供下载,希望实现原尺寸文件直接下载。
现有代码与配置
Classic ASP代码(已更新)
<% csfiles = "R710_firmware.zip" '2.14GB file strfileName = csfiles Response.AddHeader "content-disposition","filename=" & strfileName Response.ContentType = "application/x-zip-compressed" 'Here your content -type Dim strFilePath, lSize, lBlocks 'Const CHUNK = 20480 'Const CHUNK = 20480000 Const CHUNK = 8192 ' Updated Server.ScriptTimeout = 600 '10 minutes set objStream = CreateObject("ADODB.Stream") objStream.Open objStream.Type = 1 objStream.LoadFromfile Server.MapPath("up/files/"&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)) Response.Flush() ' Updated Loop objStream.Close %>
相关配置
Web.config
<security> <requestFiltering> <requestLimits maxAllowedContentLength="4294967295" /> </requestFiltering> </security>
IIS设置
设置MIME类型:.iso application/octet-stream
IIS/ASP:响应缓冲限制:200000000
IIS/请求筛选:最大允许内容长度(字节):4294967295(4GB)
ApplicationHost.config
<requestFiltering> <requestLimits maxAllowedContentLength ="4294967295" />
错误信息
尝试下载2GB+文件时触发错误,对应代码第19行lSize = objStream.Size:
Error: -ASP_LOG_ERROR
LineNumber: 19
ErrorCode: 800a0e89
Description: Data value is too large to be represented by the field data type.
错误原因:Classic ASP的VBScript中Long类型是32位整数,最大只能存储2147483647字节(约2GB),而2.14GB文件的大小超过了这个上限,导致读取objStream.Size时溢出。
解决方案
方案1:修改现有Classic ASP脚本
核心思路:避免32位整数溢出问题,确保分块流式传输不加载整个文件到内存。
简化版(跳过Content-Size)
如果不需要浏览器显示下载进度,可以直接跳过Content-Size的设置,避免读取超大文件的尺寸:
<% csfiles = "R710_firmware.zip" '2.14GB file strfileName = csfiles Response.AddHeader "content-disposition","filename=" & strfileName Response.ContentType = "application/x-zip-compressed" Const CHUNK = 8192 Server.ScriptTimeout = 600 '10 minutes Response.Buffer = False ' 禁用响应缓冲,避免内存溢出 Set objStream = CreateObject("ADODB.Stream") objStream.Open objStream.Type = 1 ' 二进制模式 objStream.LoadFromFile Server.MapPath("up/files/" & strfileName) ' 跳过Content-Size设置,避免32位整数溢出 Do Until objStream.EOS Or Not Response.IsClientConnected Response.BinaryWrite objStream.Read(CHUNK) Response.Flush() ' 立即发送当前块到客户端 Loop objStream.Close Set objStream = Nothing %>
完整版(支持Content-Size)
如果需要浏览器显示下载进度,使用WMI获取64位文件大小(避免32位FileSystemObject的限制):
<% csfiles = "R710_firmware.zip" '2.14GB file strfileName = csfiles strFilePath = Server.MapPath("up/files/" & strfileName) Response.AddHeader "content-disposition","filename=" & strfileName Response.ContentType = "application/x-zip-compressed" Const CHUNK = 8192 Server.ScriptTimeout = 600 '10 minutes Response.Buffer = False ' 禁用响应缓冲 ' 通过WMI获取64位文件大小 Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") Set colFiles = objWMIService.ExecQuery("SELECT Size FROM CIM_DataFile WHERE Name='" & Replace(strFilePath, "\", "\\") & "'") For Each objFile In colFiles Response.AddHeader "Content-Size", objFile.Size Next Set objStream = CreateObject("ADODB.Stream") objStream.Open objStream.Type = 1 ' 二进制模式 objStream.LoadFromFile strFilePath Do Until objStream.EOS Or Not Response.IsClientConnected Response.BinaryWrite objStream.Read(CHUNK) Response.Flush() ' 立即发送当前块 Loop objStream.Close Set objStream = Nothing Set objWMIService = Nothing Set colFiles = Nothing %>
方案2:ASP.NET Web Forms处理程序(非Core/Razor)
使用ASP.NET的一般处理程序(ASHX)实现流式分块下载,天然支持64位文件大小:
C#版本(LargeFileDownloadHandler.ashx)
<%@ WebHandler Language="C#" Class="LargeFileDownloadHandler" %> using System; using System.IO; using System.Web; public class LargeFileDownloadHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { string fileName = "R710_firmware.zip"; string filePath = context.Server.MapPath("~/up/files/" + fileName); if (!File.Exists(filePath)) { context.Response.StatusCode = 404; return; } // 设置响应头 context.Response.ContentType = "application/x-zip-compressed"; context.Response.AddHeader("Content-Disposition", $"attachment; filename={fileName}"); context.Response.AddHeader("Content-Size", new FileInfo(filePath).Length.ToString()); // 禁用缓冲,流式传输 context.Response.BufferOutput = false; int chunkSize = 8192; byte[] buffer = new byte[chunkSize]; using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { long bytesRead; // 分块读取并发送 while ((bytesRead = fs.Read(buffer, 0, chunkSize)) > 0 && context.Response.IsClientConnected) { context.Response.OutputStream.Write(buffer, 0, (int)bytesRead); context.Response.Flush(); } } context.Response.End(); } public bool IsReusable => false; }
VB.NET版本(LargeFileDownloadHandler.ashx)
<%@ WebHandler Language="VB" Class="LargeFileDownloadHandler" %> Imports System Imports System.IO Imports System.Web Public Class LargeFileDownloadHandler : Implements IHttpHandler Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest Dim fileName As String = "R710_firmware.zip" Dim filePath As String = context.Server.MapPath("~/up/files/" & fileName) If Not File.Exists(filePath) Then context.Response.StatusCode = 404 Return End If ' 设置响应头 context.Response.ContentType = "application/x-zip-compressed" context.Response.AddHeader("Content-Disposition", $"attachment; filename={fileName}") context.Response.AddHeader("Content-Size", New FileInfo(filePath).Length.ToString()) ' 禁用缓冲 context.Response.BufferOutput = False Dim chunkSize As Integer = 8192 Dim buffer(chunkSize - 1) As Byte Using fs As New FileStream(filePath, FileMode.Open, FileAccess.Read) Dim bytesRead As Long = fs.Read(buffer, 0, chunkSize) While bytesRead > 0 AndAlso context.Response.IsClientConnected context.Response.OutputStream.Write(buffer, 0, CInt(bytesRead)) context.Response.Flush() bytesRead = fs.Read(buffer, 0, chunkSize) End While End Using context.Response.End() End Sub Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property End Class
内容的提问来源于stack exchange,提问作者CodingEE
相关产品推荐
相关产品推荐

