验证 VB.Net SSIS 包中的 Zip 文件

Validating Zip File in VB.Net SSIS Package

早上好,

我正在使用 Microsoft SSIS 执行从文件系统到 MS SQL 数据库的数据迁移,其中我使用的一些文件是 .zip 压缩文件夹。一些压缩文件夹已经损坏,我想在导入过程中忽略这些。

我创建的是一个 VB.Net 脚本任务,用于检查给定目录的压缩文件是否有效,但我的 Try-Catch 块仅适用于第一个损坏的压缩文件。我已经尝试了 Try-Catch 的一些变体,但我无法弄清楚如何让块在第二个损坏的 zip 之后继续。

这让我觉得我的 catch 块中需要进行一些垃圾收集,因为第一个异常填充了 The thread 0x000a has exited with code 0 (0x0). 的列表,后跟 Exception thrown: 'System.IO.InvalidDataException' in System.IO.Compression.FileSystem.dll 而第二个只列出了线程退出,没有抛出异常。

我试过的如下:

'Attempt to extract the zip contents
Try
    System.IO.Compression.ZipFile.ExtractToDirectory(str_dirExtractFrom, str_dirExtractTo)
Catch ex As InvalidDataException
    Console.WriteLine("Corrupted Zip " & str_dirExtractFrom)
End Try

'A helper function to determine if a zip file is valid:
Private Function IsValidZip(ByRef rstr_filePath As String) As Boolean
    Dim zip_file As Compression.ZipArchive
    Try
        zip_file = System.IO.Compression.ZipFile.OpenRead(rstr_filePath)
        'Added in attempts to force a reset
        If Not zip_file Is Nothing Then
            zip_file.Dispose()
            Return True
        End If
    Catch ex As InvalidDataException
        Return False
    End Try
End Function

'Using both together
bool_validZip = IsValidZip(str_dirExtractFrom)
If bool_validZip Then
    Try
        System.IO.Compression.ZipFile.ExtractToDirectory(str_dirExtractFrom, str_dirExtractTo)
    Catch ex As Exception
        Console.WriteLine("Generic Exception from " & str_dirExtractFrom)
    End Try
End If

奇怪的是,回到 VBA 使用 On Error Resume Next 的解决方案确实提供了我正在寻找的结果,但我怀疑这会对性能产生影响,因为它开始在每个损坏上花费越来越长的时间zip 继续下一个文件。 我的工作代码是一个更简单但看似不正确的解决方案:

On Error Resume Next
System.IO.Compression.ZipFile.ExtractToDirectory(str_dirExtractFrom, str_dirExtractTo)
If Err.Number <> 0 Then 
    Err.Clear()
    Return False
On Error GoTo 0

有什么方法可以在此脚本任务中使用 Try-Catch 块吗?我是否需要更改我的 SSIS 控制流以使脚本任务仅在一个文件上执行而不是查询目录?或者使用更简单的 Resume Next 才是正确的解决方案?

感谢您花时间阅读我的帮助请求,感谢您的帮助!

我假设您有 zip 文件的列表或数组。您正在遍历文件并提取。您需要一个 Contiue For 才能继续前进。

Private Sub ExtractZip()
    Dim str_dirExtractTo = "Where TypeOf extract to"
    Dim ListToExtract As New List(Of String) 'List of the zip files
    For Each str_dirExtractFrom In ListToExtract
        Try
            System.IO.Compression.ZipFile.ExtractToDirectory(str_dirExtractFrom, str_dirExtractTo)
        Catch ex As InvalidDataException
            Console.WriteLine("Corrupted Zip " & str_dirExtractFrom)
            'If you want to delete the corrupt file, do it here
            Continue For
        End Try
    Next
End Sub

在回答我自己的问题时,我找到了一个解决方案,该解决方案一直对我有用。

首先,Try-Catch 会起作用。在我的例子中,由于文件大小和机器可用的资源,它只需要比预期更长的时间来工作。留给自己的设备,及时它能够处理第二个和后续损坏的 zip 文件。

进一步分析一下,跳过尝试从 OpenRead 分配对象比直接尝试从那里提取内容并捕获异常稍微更有效。下面的代码在决策树的一部分的 For-Each 循环中被调用,但不需要 Continue For.

我的部分经验包括了解到,使用 SSIS,使用脚本任务单步执行目录中的每个文件不如使用内置的 Foreach 功能有效。比我更有能力的人可能会在我原来的解决方案中进行垃圾收集以释放内存,但使用 SSIS 的控制流 Foreach 容器可以更好地解决内存问题 运行。

Private Function ExtractValidZip(ByRef rstr_dirExtractFrom As String, ByRef rstr_dirExtractTo As String) As Boolean
' Returns
' True - successful unzip to target directory
' False - failure to unzip

    Try
        System.IO.Compression.ZipFile.ExtractToDirectory(rstr_dirExtractFrom, rstr_dirExtractTo)
        Return True
    Catch ex As InvalidDataException
        Return False
    Catch ex As Exception
        Console.WriteLine("Generic Exception from " & rstr_dirExtractFrom ) 'Hasn't occurred yet
        Return False
    End Try
End Function