C#和SQL Server不一致关于字符串是否有效Base64 - 哪个是正确的?

时间:2014-02-21 16:32:43

标签: sql-server sql-server-2008-r2 base64

我们在SQL Server 2008 R2(SP1)数据库上有以下表格:

-- irrelevant columns omitted
create table Person
           ( PersonID int,
             Portrait varchar(max) )

Person.Portrait列包含从JPG图像编码的Base64字符串 - 这是由我们无法控制的第三方系统填充的。我需要将此数据转换回原始字节,以便我可以在报告中显示它:

select isnull(cast(N'' as xml).value('xs:base64Binary(sql:column("psn.Portrait"))', 'varbinary(max)'), 0xdeadbeef) as [Portrait]
  from Person psn with (nolock)
 where psn.PersonID = <n>

对于某些行,这将返回有效的varbinary数据;对于其他行,它返回OxDEADBEEF(换句话说,XML表达式的结果返回null)。

但是,如果我针对Person表中在SQL Server中返回null的行运行以下C#代码,我将获得有效的JPG图像输出:

var portraitBytes = Convert.FromBase64String(Sql.SelectSingleString(
@"select psn.Portrait
    from Person psn with (nolock)
   where psn.PersonID = <n>"));

using (var writer = new FileStream(@"C:\portrait.jpg", FileMode.CreateNew))
{
  writer.Write(portraitBytes, 0, portraitBytes.Length);
}

我在SQL Server被视为“有效”的值与“无效”的值之间看到的唯一区别是“无效”值以字符Z结尾。如果我用=替换此字符,那么SQL Server很高兴。

如果我在以Z结尾的Base64字符串上运行上述C#代码,但该字符替换为=,则代码运行正常,结果输出的图像小1个字节,但(显然) )渲染相同。

所以我的问题:

  1. 使用Z结束Base64字符串是否有效?
  2. 哪一个行为不端:C#接受无效的Base64字符串,还是SQL Server拒绝有效的字符串?
  3. Z替换=以允许SQL Server不要呕吐是否安全?换句话说,结果字节是否有可能不是有效的JPG数据?

1 个答案:

答案 0 :(得分:2)

  1. 两者都没有,见下文。
  2. 不再相关,见下文。
  3. 经过多次探索后,我发现psn.Portrait中的数据包含一个尾随NUL\0)字符,在SQL Server管理中运行select时不会显示该字符工作室。因此,每次我从SSMS复制数据以作为文字进行测试时,它都不会有尾随NUL,因此会正确解码。当然,在引用列中的实际值时,NUL出现了,并导致MSSQL正确拒绝该字符串。

    在C#方面,事实证明Sql.SelectSingleString辅助方法在其中有一行显示result.Trim('\0')。为什么它在那里我无法理解,但这解释了为什么C#没有在NUL上窒息......它不会在那里窒息。