Проблема: у меня есть база данных, в которой файлы находятся в столбце varbinary (max). Я знаю тип файла, потому что есть поле расширения. Мне нужно вытащить данные и сохранить файлы в файловой системе. У меня не так много информации о том, как хранятся данные. В БД это выглядит так:
Я пробовал несколько разных подходов, чтобы получить это значение и сохранить его как файл. Я могу легко создавать файлы из данных, но они всегда повреждены. Я получаю это сообщение при открытии PDF-файла.
Я получаю сообщение аналогичного типа, если это файл Excel. (xls) Я пробовал следующие методы для доступа к данным, первые 2 с использованием считывателя SQL с или без commandBehaviour.sequentialAccess. Третий использует SQL Substring.
byte[] data = (byte[])reader["Data"];
// OR
int ordinal = reader.GetOrdinal("Data");
long bufferSize = reader.GetBytes(ordinal, 0, null, 0, 0);
byte[] outbyte = new byte[bufferSize];
reader.GetBytes(ordinal, 0, outbyte, 0, (int)bufferSize);
// OR
public System.IO.Stream GetStream(AttachmentModel info)
{
var attachment = (AttachmentModel)info;
int start = 0;
int packetSize = 65535;
int length = packetSize;
byte[] data = new byte[info.length];
while (start < info.length)
{
length = Math.Min(packetSize, ((int)info.length - start));
byte[] buffer = repo.ReadAttachmentData(attachment.id, start, length);
buffer.CopyTo(data, start);
start += length;
}
return new MemoryStream(data);
}
// ReadAttachmentData method
public byte[] ReadAttachmentData(Guid attachmentID, int start, int length)
{
using (SqlConnection connection = GetOpenSqlConnection())
{
using (SqlCommand cmd = connection.CreateCommand())
{
byte[] buffer = null;
cmd.CommandText = @"SELECT SUBSTRING([Data], @start, @length) FROM myBlobTable WHERE [Attachment] = @attachmentID";
cmd.CommandType = CommandType.Text;
AddParamWithValue(cmd, "@start", DbType.Int32, start + 1); // index starts at 1
AddParamWithValue(cmd, "@length", DbType.Int32, length);
AddParamWithValue(cmd, "@attachmentID", DbType.Guid, attachmentID);
buffer = (byte[])cmd.ExecuteScalar();
return buffer;
}
}
}
private IDataParameter AddParamWithValue(SqlCommand cmd, string name, DbType type, object value)
{
IDbDataParameter param = cmd.CreateParameter();
param.ParameterName = name;
param.DbType = type;
param.Value = (value ?? DBNull.Value);
param.Size = 0;
param.Direction = ParameterDirection.Input;
cmd.Parameters.Add(param);
return param;
}
Чтобы сохранить данные в файл, я пробовал:
System.IO.File.WriteAllBytes(fileName, byteArray);
// OR
using (Stream st = GetStream(att))
{
using (FileStream fs = new FileStream(att.filePath + "File1" + att.extension, FileMode.Create, FileAccess.Write))
{
st.CopyTo(fs);
st.Flush();
fs.Flush();
st.Close();
fs.Close();
}
};
// I tried using the deflate stream thinking maybe it was compressed.
using (Stream st = GetStream(attachment))
using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
{
st.CopyTo(fs);
st.Flush();
fs.Flush();
st.Close();
fs.Close();
}
Я также пробовал использовать параметры размера буфера в моем FileStream. Я безуспешно пробовал практически все комбинации описанных выше методов доступа к данным и сохранения данных.
Еще одна подсказка - если я открою файл в блокноте, данные будут выглядеть так:
data:; base64, JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGg .... et c, et c.
Любая помощь приветствуется, спасибо!