【问题标题】:Extracting base64-encoded images from XML using SSIS使用 SSIS 从 XML 中提取 base64 编码的图像
【发布时间】:2021-05-06 22:17:55
【问题描述】:

我有一个复杂的场景,客户发送XML 文件,我应该从这些文件中提取一些信息。一个重要信息是使用base64 编码的图像。

xmlxsd文件,定义了包含base64编码图像的元素如下:

   <xs:element name="image" type="xs:base64Binary" nillable="false" minOccurs="0" maxOccurs="unbounded">
      <xs:annotation>
        <xs:documentation xml:lang="en">
          base64 image.
        </xs:documentation>
      </xs:annotation>
    </xs:element> 

在 SSIS 中,我使用XML Source 组件来提取元素。在组件的“输入和输出属性”中,我将数据类型(在与 base64-image 元素相关的外部/输出列中)定义为image [DT_IMAGE] 类型。

Q1:选择这种数据类型读取base64编码的图片是否正确? byte stream [DT_BYTES] 或者只是 string [DT_STR] 呢?

接下来,我将组件的输出传递给 Recordset Destination 以将输出存储在类型为 Object 的 SSIS 变量 User::xml_image 中(我这样做是因为可能有多个图像)。

然后将对象变量传递给Script Task,转换为DataTable,我正在尝试将“假设第一行/图像”保存到文件系统中。我使用的代码如下:

            DataTable table = new DataTable();
            oleAdapter.Fill(table, Dts.Variables["xml_image"].Value);

            Image image;
            BinaryFormatter bf = new BinaryFormatter();
            var ms = new MemoryStream();

            // convert the first image
            bf.Serialize(ms, table.Rows[0]["image"]);
            byte[] bytes = ms.ToArray();

            using (MemoryStream mem = new MemoryStream(bytes))
            {
                mem.Seek(0, SeekOrigin.Begin);
                image = Image.FromStream(mem); // error in this line: Parameter is not valid.
                image.Save("D:\\tepack.jpeg", ImageFormat.Jpeg);
            }

脚本一直执行,直到调用FromStream 方法并失败并出现此错误:

参数无效。

Q2:如何修复代码错误,并成功保存图像,考虑以上场景和配置?

【问题讨论】:

    标签: c# xml ssis xsd


    【解决方案1】:

    A1. DT_IMAGE vs DT_BYTES VS DT_STR

    根据定义,base64 编码二进制是 ASCII 字符串数据,因此数据的初始提取将是 DT_STR也许

    此时,您拥有 XML 中的字符,您可以通过目视检查以确认是的,我从 XML 中正确提取了该字段。

    下一步是将base64编码或decode反转为原始二进制位。

    A2. Image.FromStream 错误

    我不确定Image 类的来源,但它可能正在尝试将数据转换为不同的图像格式(png 到 jpg 到 bmp 等),但是你在内存中的位已经 是您需要的位。您只需要将字节数组写入磁盘,类似于

    https://www.oreilly.com/library/view/c-cookbook/0596003390/ch02s12.html

    byte[] imageBytes = Base64DecodeString(bmpAsString);
    fstrm = new FileStream(@"C:\winnt_copy.bmp", FileMode.CreateNew, FileAccess.Write);
    BinaryWriter writer = new BinaryWriter(fstrm);
    writer.Write(imageBytes);
    writer.Close( );
    fstrm.Close( );
    

    也许 在线书籍数据类型的链接指出了数据类型的最大长度,我们看到 DT_STR 是 8000 个字符,而 DT_IMAGE/DT_BYTES/DT_TEXT 是 210 万个单位(字符或字节)。由于这些都不是 unicode 数据,因此它们的成本存储成本都是相同的,但没有任何 Expression 语言可以对数据进行操作(除了 null 和长度检查 IIRC),并且数据查看器将集中在其中,因此可以进行目视检查具有挑战性。

    jpg 是一种压缩文件格式 - 他们丢弃数据以减少字节数。但是 Base64 是反压缩的,因为它在将危险的二进制字符映射为安全的 ascii 字符时会扩大大小。因此,除非您知道源图像非常小,否则您可能会超出 8000 个字符的边界。

    假设通货膨胀率为 1.3,您看到的最大原始大小约为 5970 字节。一个 6kb 的 jpg 文件可能很小且质量低下。例如这张图片是 5151 字节

    最后的想法 当我输入此内容并考虑问题域时,除非您有充分的理由使用数据流,否则我会在这种情况下避免使用它。相反,使用脚本任务来分解 XML。如果您不必担心将数据类型适合 SSIS 原始类型以及您的所有操作都已经是 .NET 脚本操作这一事实,那么我认为您会遇到更少的问题。

    【讨论】:

    • 好吧,我的问题没有解决,但是我最终采用了您建议的方法,通过脚本任务处理 XML 并且有效:)
    猜你喜欢
    • 1970-01-01
    • 2017-11-02
    • 2022-08-21
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    相关资源
    最近更新 更多