【发布时间】:2017-04-06 08:33:37
【问题描述】:
我有一个将文件保存到 sqlserver 数据库 (2014) 的 C# winforms 应用程序 到 varbinary(MAX) 字段
保存功能
byte[] Bytefile;
using (SqlConnection conn = new SqlConnection(DataHelper.GetConnection()))
{
conn.Open();
DataTable dt = new DataTable();
SqlCommand comm = new SqlCommand("Delete T_Articale_Files where Artricle_id=" + ID, conn);
comm.ExecuteNonQuery();
foreach (string file in Directory.GetFiles(varFilePath))
{
using (var stream = new FileStream(Path.Combine(varFilePath, file), FileMode.Open, FileAccess.Read))
{
using (var reader = new BinaryReader(stream))
{
Bytefile = reader.ReadBytes((int)stream.Length);
}
}
using (var sqlWrite = new SqlCommand("INSERT INTO T_Articale_Files (Artricle_id,FileName,FileData) Values(@ID,@FileName,@File)", conn))
{
sqlWrite.Parameters.Add("@ID", SqlDbType.Int, 10).Value = ID;
sqlWrite.Parameters.Add("@FileName", SqlDbType.NVarChar, 50).Value = Path.GetFileName(file);
sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = Bytefile;
sqlWrite.ExecuteNonQuery();
}
}
}
检索函数
using (SqlConnection conn = new SqlConnection(DataHelper.GetConnection()))
// using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
{
conn.Open();
DataTable dt = new DataTable();
SqlCommand comm = new SqlCommand("SELECT id,FileName FROM T_Articale_Files WHERE Artricle_id = @varID", conn);
comm.Parameters.AddWithValue("@varID", varID);
dt.Load(comm.ExecuteReader());
foreach (DataRow item in dt.Rows)
{
using (var sqlQuery = new SqlCommand(@"SELECT FileData FROM T_Articale_Files WHERE id = @ID", conn))
{
sqlQuery.Parameters.AddWithValue("@ID", item["id"]);
using (var sqlQueryResult = sqlQuery.ExecuteReader())
while (sqlQueryResult.Read())
{
var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))];
sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length);
using (var fs = new FileStream(Path.Combine(varPathToNewLocation, item["FileName"].ToString()), FileMode.Create, FileAccess.Write))
fs.Write(blob, 0, blob.Length);
}
}
}
}
工作正常 现在我已经要求将数据库转换为 XML 用于没有连接到服务器的 PC
转换为 XML 的函数
var xmlFileData = "";
DataSet ds = new DataSet();
var tables = new[] { "V_Articale", "T_Articale", "T_City", "T_Classification", "T_Country", "T_Locations", "T_milishia", "T_Search", "T_statistics", "T_TerrorGroups", "T_Tribes", "T_Users", "T_Articale_Files" };
foreach (var table in tables)
{
var query = "SELECT * FROM " + table;
SqlConnection conn = GetConnection();
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable(table);
da.Fill(dt);
conn.Close();
conn.Dispose();
ds.Tables.Add(dt);
if(table== "T_Articale_Files")
{
foreach (DataRow item in dt.Rows)
{
Byte[] file = GetBytes(item["FileData"].ToString());
}
}
}
xmlFileData = ds.GetXml();
除了二进制文件外,它工作正常
时将其转换为文本输出 XML
<T_Articale_Files>
<id>6</id>
<Artricle_id>1013</Artricle_id>
<FileName>falcon banner.jpg</FileName>
<FileData>/9j/4AAQSkZJRgABAgEASABIAAD/4QleRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUA</FileData>
当尝试将其转换回图像时,它给了我 1kb 的文件,其中的字符串不是实际图像
二进制字段是否有特殊转换 请指教
谢谢
感谢@grek40 解决了编辑问题 解决方案转换为 XML
var xmlstream = new StringWriter();
ds.WriteXml(xmlstream, XmlWriteMode.WriteSchema);
string xmlWithSchema = xmlstream.ToString();
其中 ds 是一个数据集
转回文件
private void databaseFileRead(int varID, string varPathToNewLocation)
{
DataSet ds = new DataSet();
ds.ReadXml(XMLpath);
DataTable dt = new DataTable();
dt = ds.Tables["T_Articale_Files"];
DataView dv = new DataView(dt);
dv.RowFilter = "Artricle_id=" + varID;
if (dv.Count > 0)
{
foreach (DataRowView item in dv)
{
byte[] stringArray = (byte[])(item["FileData"]);
File.WriteAllBytes(Path.Combine(Filepath, item["FileName"].ToString()), stringArray ); // save image to disk
}
}
【问题讨论】:
-
如果你不 .ToString() 你的 FileData 怎么办?字节[] 文件 = GetBytes(item["FileData"]);而不是 Byte[] file = GetBytes(item["FileData"].ToString());
-
对于二进制数据,永远不要使用 ToString(),它总是会搞砸数据。最好将 Encoding.UTF8 与 GetBytes() 或 GetString() 方法一起使用;字符串/char 是两个字节,具有表示 char 是一个字节还是两个字节的受保护属性。当您使用 ToString() 方法时,它可能会在确定一个字符是一个字符还是两个字符时出错。使用 UTF8 将强制每个字符为一个字节。
-
如果你在谈论 if(table== "T_Articale_Files") { foreach (DataRow item in dt.Rows) { Byte[] file = GetBytes(item["FileData"].ToString() );我评论了该代码并使用了没有它的方法
-
如果你问 GetBytes 是什么 static byte[] GetBytes(string str) { byte[] bytes = new byte[str.Length * sizeof(char)]; System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);返回字节; }
-
@Maher Khalil 不,它实际上在您的“转换为 XML”功能中。当您将 varbinary(MAX) 转换为 Byte[]
标签: c# sql-server xml