We have the following table on a SQL Server 2008 R2 (SP1) database:
-- irrelevant columns omitted
create table Person
           ( PersonID int,
             Portrait varchar(max) )
The Person.Portrait column contains Base64 strings encoded from JPG images - this is populated by a third-party system we have no control over. I need to convert this data back to raw bytes so I can display it in a report:
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>
For some rows this is returning valid varbinary data, for others it's returning OxDEADBEEF (in other words, the result of the XML expression is returning null).
However, if I run the following C# code against the rows in the Person table that are returning null in SQL Server, I get valid JPG images output:
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);
}
The only differences I can see between the values that are seen as "valid" by SQL Server, versus those that are "invalid", is that the "invalid" ones end with the character Z. If I replace this character with = then SQL Server is happy.
If I run the above C# code on a Base64 string ending in Z, but with that char replaced by =, the code runs fine and the resulting outputted image is 1 byte smaller but (apparently) renders identically.
So my questions:
- Is it valid to end a Base64 string with Z?
- Which one is misbehaving: C# by accepting an invalid Base64 string, or SQL Server by rejecting a valid one?
- Is it safe to replace Zwith=to allow SQL Server to not puke? In other words, is there a possibility that the resulting bytes will not be valid JPG data?
