You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求支持超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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:27:04