在c#中将SQL映像转换为Base64



我有一个数据库,存储具有两个不同文件签名的二进制JPEG图像(FFD8FFE0和FFD8DDE1),我想将它们转换为Base64,以便我可以在另一个应用程序(Power BI)中使用它们。数据存储为IMAGE字段类型,但是我只接收CSV文件中的数据,并将其作为字符串导入到我的工具中,并从那里使用它。

对于文件签名FFD8FFE0,我使用下面的代码转换没有问题(来自另一个Stack帖子-谢谢):

public static string ToBase64(String sBinary)
{
int noChars = sBinary.Length;
byte[] bytes = new byte[noChars / 2];
for (int i = 0; i < noChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(sBinary.Substring(i, 2), 16);
}
return Convert.ToBase64String(bytes);
}

但是,文件签名FFD8FFE1不能正确地转换和显示为图像。它给了我一个输出,但是没有正确显示。

任何建议吗?这是因为不同的文件签名还是因为字符串的大小(它们明显更大)?

编辑:谢谢所有帮助我的人。正如评论中提到的,真正的问题是我试图转换的数据——它在CSV中被截断了。所以对于任何遇到这篇文章的人来说,直接从SQL而不是文本文件中拉出,因为数据很有可能被截断.

听起来像是从管理工具的查询结果中导出了二进制数据。这些工具几乎总是截断显示的二进制结果以节省内存。

使用ADO直接从数据库读取数据会更好,也更容易。. NET或像Dapper这样的micro-ORM来减少样板代码。

使用Dapper,你可以写一些像这样简单的东西:

var sql="select image from MyTable where Category=@category";
using var connection=new SqlConnection(connectionString);
var images=connection.Query<byte[]>(sql,new {category="Cats"});
并将其转换为:
var cats64=images.Select(bytes=>Convert.ToBase64String(bytes));

Dapper将处理打开和关闭连接,所以我们甚至不需要这样做。

如果你想检索更多的字段,你可以定义一个类来接受结果。Dapper将结果列按名称映射到属性。一旦有了类,就可以很容易地添加一个方法来返回Base64字符串:

class MyData
{
public string Name{get;set;}
public byte[] Image {get;set;}
public string ToBase64()=>Convert.ToBase64String(Image);
}

....
var images=connection.Query<MyData>("select Name,Image From ....",...);

使用普通的旧ADO。NET需要更多的行:

var sql="select image from MyTable where Category=@category";
using var connection=new SqlConnection(connectionString);
using var cmd=new SqlCommand(sql,connection);
cmd.Parameters.Add("@category",SqlDbType.NVarChar,20).Value="Cats";
using var reader=cmd.ExecuteReader();
while(reader.Read())
{
var image=(byte[])reader["image"];
...
}

ADO。但是,也可以将数据加载为,而不是将所有内容加载到内存中。当图像很大时,这非常有用,因为我们避免了将整个blob缓存到内存中。可以直接将流写入文件,而不需要先将其加载到内存中:

while(reader.Read())
{
using (var stream=reader.GetStream(0))
using (var file=File.Create(somePath))
{
stream.CopyTo(file);
}
}

没有超载的Convert.ToBase64String与流工作。可以使用带Base64变换的CryptoStream类将流转换为将输入流编码为Base64,如此SO答案所示。在这种情况下采用它:

while(reader.Read())
{
using (var stream.      = reader.GetStream(0))
using (var base64Stream = new CryptoStream( stream, new ToBase64Transform(), CryptoStreamMode.Read ) )
using (var outputFile   = File.Create(somePath) )
{
await base64Stream.CopyToAsync( outputFile ).ConfigureAwait(false);
}

如果您希望转换为base64 jpg url:

public static string ToBase64PNGUrl (byte[] bytes) =>
$"data:image/jpg;base64,{Convert.ToBase64String(bytes)}";

从数据库映射结果不正确,该字段应该是byte[],而不是字符串。

我假设您正在接收字节的十六进制表示,您可以将其转换为字节,然后在尝试(Convert.ToBase64String(bytes))时转换为base64。

尝试先使用EF-code从表中读取,并将image属性定义为byte[]。

最新更新