VB.NET脚本调用SSRS报告URL时大文件生成异常问题
问题分析与解决方案
核心问题
你的脚本在下载大体积SSRS Excel文件时,因流读取不完整或异常未捕获导致中断,生成损坏的文件。浏览器直接访问正常说明SSRS本身能生成完整文件,问题出在VB.NET的下载逻辑上。
具体问题点
- 缓冲区过小:仅用256字节缓冲区读取大文件,频繁的IO操作容易引发中断,导致文件写入不完整。
- 异常被静默忽略:
Catch ex As Exception块为空,下载过程中发生的错误(如连接中断、超时)无法被发现,直接生成残缺文件。 - 资源未正确释放:
FileStream和HttpWebResponse没有用Using语句自动释放,可能导致资源泄漏或文件写入不完整。 - 未设置ReadTimeout:仅设置了请求超时,未设置响应流的读取超时,大文件读取时可能因超时中断。
修改后的脚本
Imports System Imports System.Data Imports System.Math Imports Microsoft.SqlServer.Dts.Runtime Imports System.ComponentModel Imports System.Diagnostics <Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute()> <System.CLSCompliantAttribute(False)> Partial Public Class ScriptMain Inherits Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase Enum ScriptResults Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure End Enum Protected Sub SaveFile(ByVal url As String, ByVal localpath As String) ' 使用Using自动释放资源,避免泄漏 Using loFileStream As New System.IO.FileStream(localpath, System.IO.FileMode.Create, System.IO.FileAccess.Write) Dim loRequest As System.Net.HttpWebRequest = CType(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest) loRequest.Credentials = System.Net.CredentialCache.DefaultCredentials loRequest.Timeout = 600000 ' 调整为10分钟(根据实际情况修改) loRequest.ReadWriteTimeout = 300000 ' 添加读取/写入超时,5分钟 loRequest.Method = "GET" Using loResponse As System.Net.HttpWebResponse = CType(loRequest.GetResponse, System.Net.HttpWebResponse) Using loResponseStream As System.IO.Stream = loResponse.GetResponseStream Dim bufferSize As Integer = 8192 ' 增大缓冲区到8KB,提升读取效率 Dim laBytes(bufferSize - 1) As Byte Dim liCount As Integer Do liCount = loResponseStream.Read(laBytes, 0, bufferSize) If liCount > 0 Then loFileStream.Write(laBytes, 0, liCount) End If Loop While liCount > 0 loFileStream.Flush() End Using End Using End Using End Sub Public Sub Main() Try Dim url, destination As String destination = String.Format("{0}\{1}{2}.xlsx", _ Dts.Variables("Folder_Destination").Value.ToString, _ Dts.Variables("ReportName").Value.ToString, _ Dts.Variables("OutPutDate").Value.ToString) url = String.Format("{0}{1}{2}&StartDate={3}&EndDate={4}&RUNTYPE=2&rs:Format=EXCELOPENXML", _ Dts.Variables("ReportURL").Value.ToString, _ Dts.Variables("Location").Value.ToString, _ Dts.Variables("ServiceArea").Value.ToString, _ Dts.Variables("START_DATE").Value.ToString, _ Dts.Variables("END_DATE").Value.ToString) SaveFile(url, destination) Dts.TaskResult = ScriptResults.Success Catch ex As Exception ' 捕获并记录异常,便于排查问题 Dts.Events.FireError(0, "SSRS Report Download", ex.Message & vbCrLf & ex.StackTrace, String.Empty, 0) Dts.TaskResult = ScriptResults.Failure End Try End Sub End Class
关键改进说明
- 增大缓冲区:将缓冲区从256字节改为8192字节(8KB),减少IO操作次数,提升大文件读取稳定性。
- 添加异常捕获与日志:在
Main方法中添加异常捕获,通过FireError记录错误信息,方便排查下载失败原因。 - Using语句管理资源:所有流和请求对象都用
Using包裹,确保资源自动释放,避免因资源泄漏导致的文件损坏。 - 设置ReadWriteTimeout:添加响应流的读取/写入超时,防止大文件读取时因超时中断。
- 字符串拼接优化:用
String.Format替代+拼接字符串,提升可读性和避免格式错误。
额外建议
- 检查SSIS执行超时:确保SSIS包的执行超时时间足够长,避免大文件下载过程中被SSIS强制终止。
- 验证日期格式:确认
START_DATE和END_DATE变量的格式符合SSRS要求,避免因格式问题导致部分数据未生成。 - 测试大文件下载:修改后测试4个月以上数据的下载,查看是否还有文件损坏情况;如果仍有问题,查看SSIS的错误日志获取具体异常信息。
内容的提问来源于stack exchange,提问作者gfuller40
相关产品推荐
相关产品推荐

