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

使用VB.NET脚本调用SSRS报表时大文件损坏问题

问题分析与解决方案

你的问题根源在文件流读取与资源管理环节:原代码缓冲区仅256字节,大文件读取时易出现数据截断;同时未正确释放网络流、文件流等资源,且空异常捕获会掩盖读取错误,导致生成的Excel文件损坏。

关键修改点

  • 用Using语句自动管理各类流资源,确保所有资源被正确关闭释放
  • 增大缓冲区至4KB,提升大文件读取效率,降低数据截断风险
  • 添加异常日志输出,便于排查读取过程中的错误
  • 对URL参数做编码处理,避免特殊字符导致请求异常

修改后的VB.NET代码

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Text

<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)
        Dim loRequest As System.Net.HttpWebRequest
        Dim bufferSize As Integer = 4096 ' 缓冲区调整为4KB
        Dim buffer(bufferSize - 1) As Byte
        Dim bytesRead As Integer

        Try
            loRequest = CType(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest)
            loRequest.Credentials = System.Net.CredentialCache.DefaultCredentials
            loRequest.Timeout = 600000 ' 超时设为600秒(原数值过大)
            loRequest.Method = "GET"

            ' Using自动释放响应资源
            Using loResponse As System.Net.HttpWebResponse = CType(loRequest.GetResponse(), System.Net.HttpWebResponse)
                ' Using自动释放响应流资源
                Using responseStream As System.IO.Stream = loResponse.GetResponseStream()
                    ' Using自动释放文件流资源
                    Using fileStream As New System.IO.FileStream(localpath, System.IO.FileMode.Create, System.IO.FileAccess.Write)
                        Do
                            bytesRead = responseStream.Read(buffer, 0, bufferSize)
                            If bytesRead > 0 Then
                                fileStream.Write(buffer, 0, bytesRead)
                            End If
                        Loop While bytesRead > 0

                        fileStream.Flush()
                    End Using
                End Using
            End Using

        Catch ex As Exception
            ' 记录异常到SSIS日志
            Dts.Events.FireError(0, "SaveFile Error", ex.Message & vbCrLf & ex.StackTrace, String.Empty, 0)
            Throw ' 抛出异常标记任务失败
        End Try
    End Sub

    Public Sub Main()
        Dim url, destination As String
        destination = $"{Dts.Variables("Folder_Destination").Value.ToString()}\{Dts.Variables("ReportName").Value.ToString()}.xlsx"

        ' 对日期参数做URL编码,避免特殊字符问题
        Dim startDateEncoded As String = System.Web.HttpUtility.UrlEncode(Dts.Variables("START_DATE").Value.ToString())
        Dim endDateEncoded As String = System.Web.HttpUtility.UrlEncode(Dts.Variables("END_DATE").Value.ToString())

        url = $"{Dts.Variables("ReportURL").Value.ToString()}{Dts.Variables("Location").Value.ToString()}&SurgeonService=ALL&DaysTillReturn=90{Dts.Variables("ServiceArea").Value.ToString()}&StartDate={startDateEncoded}&EndDate={endDateEncoded}&rs:Format=EXCELOPENXML"

        Try
            SaveFile(url, destination)
            Dts.TaskResult = ScriptResults.Success
        Catch ex As Exception
            Dts.Events.FireError(0, "Main Error", ex.Message, String.Empty, 0)
            Dts.TaskResult = ScriptResults.Failure
        End Try
    End Sub
End Class

额外注意事项

  • 需在脚本编辑器的「引用」中添加System.Web程序集,用于URL编码功能
  • 大文件生成时,确保SSIS任务有足够的内存和磁盘空间支持

内容的提问来源于stack exchange,提问作者gfuller40

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:50:55