从SQL Server数据库中检索文件

时间:2013-12-17 12:05:21

标签: c# sql sql-server file-upload

我正在构建一个网站,我必须使用文件上传控件来附加支持日志/邮件等...我觉得在数据库中保存文件是更好的选择。

我正在使用以下代码上传文件。但是,我无法测试它,因为我不知道如何从数据库中检索文件。有人可以帮我这个吗?

文件类型可以是任何内容。

代码:

FileUrl = "C:\\Attachments\\"+Path.GetFileName(UploadCtrl.NavigateUrl);
FileStream fs = new FileStream(FileUrl, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
long numBytes = new FileInfo(FileUrl).Length;
buff = br.ReadBytes(Convert.ToInt32(numBytes));
SqlConnection conn = new SqlConnection(SQLSrc.ConnectionString);
conn.Open();
SqlCommand command = conn.CreateCommand();
string InsertQueryText = "insert into Attachments values ('" + Path.GetFileName(FileUrl) + "','" + MIME(Path.GetExtension(Att_Overview_Link.NavigateUrl)) + "','" + buff + "');";
command.CommandText = InsertQueryText;
command.ExecuteNonQuery();

这里,MIME是用户定义的函数,用于获取指定文件类型的MIME值。

前端:C#ASP.NET和SQL Server作为后端

2 个答案:

答案 0 :(得分:2)

首先修复代码以删除SQL Injection vulnerability

FileUrl = "C:\\Attachments\\" + Path.GetFileName(UploadCtrl.NavigateUrl);

using (SqlConnection conn = new SqlConnection(SQLSrc.ConnectionString))
using (SqlCommand command = conn.CreateCommand())
{
   command.CommandText = "insert into Attachments values (@FileName, @MimeType, @FileBytes)";
   command.Parameters.AddWithValue("@FileName", Path.GetFileName(FileUrl));
   command.Parameters.AddWithValue("@MimeType", MIME(Path.GetExtension(Att_Overview_Link.NavigateUrl)));
   command.Parameters.AddWithValue("@FileBytes", File.ReadAllBytes(FileUrl));

   conn.Open();
   command.ExecuteNonQuery();
}

NB:我不确定您的UploadCtrl是什么,但大多数文件上传控件都提供了对Stream的上传文件的直接访问权限,而不是文件名在服务器上。根据此特定控件的工作方式,您可能需要更改读取上载文件的方式。

要检索文件,您可以选择相关的名称,MIME类型和字节,并将它们写入响应:

using (SqlConnection conn = new SqlConnection(SQLSrc.ConnectionString))
using (SqlCommand command = conn.CreateCommand())
{
   command.CommandText = "SELECT FileName, MimeType, FileBytes FROM Attachments WHERE PK = @PK";
   command.Parameters.AddWithValue("@PK", Request.QueryString["pk"]);

   conn.Open();
   using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.CloseConnection))
   {
      if (reader.Read())
      {
         string name = reader.GetString(reader.GetOrdinal("FileName"));
         Response.AppendHeader("Content-Disposition", "attachment; filename=" + name);
         Response.ContentType = reader.GetString(reader.GetOrdinal("MimeType"));

         int startIndex = 0;
         byte[] buffer = new byte[4096];
         int fieldIndex = reader.GetOrdinal("FileBytes");
         int bytesRead = (int)reader.GetBytes(fieldIndex, startIndex, buffer, 0, buffer.Length);
         while (bytesRead != 0)
         {
            Response.OutputStream.Write(buffer, 0, bytesRead);
            Response.Flush();

            startIndex += bytesRead;
            bytesRead = (int)reader.GetBytes(fieldIndex, startIndex, buffer, 0, buffer.Length);
         }
      }
   }
}

答案 1 :(得分:0)

如果您使用的是SQL Server 2008或更新版本,则可以将FILESTREAM存储用于varbinary(max)数据类型。 This MSDN article包含一些C#示例代码,可以完成您要执行的操作。它还显示了如何创建用于存储文件的表。