问题描述
我有一个复杂的场景,客户发送 XML
文件,我应该从这些文件中提取一些信息。一个重要的信息是以 base64
编码的图像。
xsd
的 xml
文件,定义了包含 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]
类型。
问题 1: 选择这种数据类型来读取 base64 编码的图像是否正确? byte stream [DT_BYTES]
或只是 string [DT_STR]
怎么样?
接下来,我将组件的输出传递给 Recordset Destination
以将输出存储在类型为 User::xml_image
的 SSIS 变量 Object
中(我这样做是因为可能有多个图片)。
然后将对象变量传递给 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:如何修复代码错误,并成功保存图片,考虑以上场景和配置?
解决方法
A1. DT_IMAGE vs DT_BYTES VS DT_STR
根据定义,base64 编码的二进制是 ASCII 字符串数据,因此数据的初始提取将是 DT_STRmaybe。
那时,您就拥有了 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 数据,因此存储成本都相同,但没有任何表达式语言可以对数据进行操作(空值和长度检查 IIRC 除外),并且数据查看器将集中在那里,因此可能需要进行目视检查要有挑战性。
jpg 是一种压缩文件格式 - 他们丢弃数据以减少字节数。但是 Base64 是反压缩的,因为它会膨胀大小,作为将危险的二进制字符映射到安全的 ascii 字符的一部分。因此,除非您知道源图像非常小,否则很可能会溢出 8000 个字符的边界。
假设通货膨胀率为 1.3,您会看到大约 5970 字节的最大原始大小。一个 6kb 的 jpg 文件可能很小而且质量很低。例如,此图像为 5151 字节
最后的想法 由于我已经输入并考虑了问题域,除非您有充分的理由使用数据流,否则在这种情况下我会避免使用它。相反,使用脚本任务来分解 XML。我认为,如果您不必担心将数据类型拟合到 SSIS 基元类型以及您的所有操作都已经是 .NET 脚本操作这一事实,那么问题就会更少。