Arrays C#从varbinary(max)字段提取文件-文件已损坏

Arrays C#从varbinary(max)字段提取文件-文件已损坏,arrays,filestream,varbinarymax,Arrays,Filestream,Varbinarymax,问题:我有一个数据库,在varbinary(max)列中有文件。我知道文件的类型,因为有一个扩展名字段。我需要取出数据并将文件保存到文件系统。关于数据是如何存储的,我没有太多的信息。在数据库中看起来是这样的: 我尝试了几种不同的方法来提取该值并将其保存为文件。我可以很容易地从数据中创建文件,但它们总是被破坏的。我在打开PDF时收到此消息。 如果是excel文件,我会收到类似类型的消息。(xls) 我尝试了以下方法来访问数据,前两种方法使用SQL读取器,使用CommandBehavior.se

问题:我有一个数据库,在varbinary(max)列中有文件。我知道文件的类型,因为有一个扩展名字段。我需要取出数据并将文件保存到文件系统。关于数据是如何存储的,我没有太多的信息。在数据库中看起来是这样的:

我尝试了几种不同的方法来提取该值并将其保存为文件。我可以很容易地从数据中创建文件,但它们总是被破坏的。我在打开PDF时收到此消息。

如果是excel文件,我会收到类似类型的消息。(xls) 我尝试了以下方法来访问数据,前两种方法使用SQL读取器,使用CommandBehavior.sequentialAccess或不使用CommandBehavior.sequentialAccess。第三个是使用SQL子字符串

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;
    }
我还尝试在文件流上使用缓冲区大小选项。我几乎尝试了上述数据访问和数据保存方法的每一种组合,但都并没有成功

另一个线索是,如果我在记事本中打开文件,数据如下所示:

数据:;base64、JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGg…等


非常感谢您的帮助,谢谢

我找到了答案——基本上是通过残酷的尝试和错误。 根据我在记事本中打开时在文件中找到的数据,我提取base64字符串并将其转换为文件。所以我的过程是,从数据库中获取字节,提取base64字符串,转换回字节,写入文件

通过以下方式访问varbinary(max)文件:

using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
{
    List<AttachmentModel> attachments = new List<AttachmentModel>();
    while (reader.Read())
    {
        AttachmentModel att = new AttachmentModel();
        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);
        att.data = outbyte; 

        attachments.Add(att);
    }

    return attachments;
}
    using (MemoryStream ms = new MemoryStream(att.data)) {
    string fileContents;
    using (StreamReader reader = new StreamReader(ms))
    {
        fileContents = reader.ReadToEnd();
        List<string> arr = fileContents.Split(',').ToList<string>();

        // convert base 64 string back to bytes
        var myBytes = Convert.FromBase64String(arr[1]);
        System.IO.File.WriteAllBytes(att.filePath + "File1" + att.extension, myBytes);
     }
}
使用(SqlDataReader=command.ExecuteReader(CommandBehavior.SequentialAccess))
{
列表附件=新列表();
while(reader.Read())
{
AttachmentModel att=新的AttachmentModel();
int ordinal=reader.GetOrdinal(“数据”);
long bufferSize=reader.GetBytes(序号,0,null,0,0);
字节[]输出字节=新字节[bufferSize];
GetBytes(序号,0,outbyte,0,(int)bufferSize);
att.data=outbyte;
附件。添加(附件);
}
归还附件;
}
并通过以下方式转换为文件:

using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
{
    List<AttachmentModel> attachments = new List<AttachmentModel>();
    while (reader.Read())
    {
        AttachmentModel att = new AttachmentModel();
        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);
        att.data = outbyte; 

        attachments.Add(att);
    }

    return attachments;
}
    using (MemoryStream ms = new MemoryStream(att.data)) {
    string fileContents;
    using (StreamReader reader = new StreamReader(ms))
    {
        fileContents = reader.ReadToEnd();
        List<string> arr = fileContents.Split(',').ToList<string>();

        // convert base 64 string back to bytes
        var myBytes = Convert.FromBase64String(arr[1]);
        System.IO.File.WriteAllBytes(att.filePath + "File1" + att.extension, myBytes);
     }
}
使用(MemoryStream ms=新的MemoryStream(att.data)){
字符串文件内容;
使用(StreamReader=新StreamReader(ms))
{
fileContents=reader.ReadToEnd();
List arr=fileContents.Split(',').ToList();
//将基64字符串转换回字节
var myBytes=Convert.FromBase64String(arr[1]);
System.IO.File.writealBytes(att.filePath+“File1”+att.extension,myBytes);
}
}