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
Z
with=
to allow SQL Server to not puke? In other words, is there a possibility that the resulting bytes will not be valid JPG data?