使用WebApi,ajax上传文件

我想通过进行ajax调用使用WebApi上传文件,文件将保存到数据库中。 我尝试了这个链接中给出的代码。 在这里,它将收到的数据保存为硬盘驱动器作为没有指定扩展名的文件,但我想做一些事情,比如当我将文件保存到数据库时我也希望保存文件名和扩展名,如果我需要的话下载文件我可以提供文件名和扩展名。 在链接中,文件作为文件保存到硬盘驱动器,但有任何方法可以直接将文件保存到DB。

答案有几个部分。

首先,要上传文件,您可以使用包含以下代码的视图:

@using (Html.BeginForm()) {  
} @section scripts { }

其次,要接收此数据,请使用以下方法创建控制器:

 public class FileController : ApiController { [HttpPost] public async Task Upload() { var provider = new MultipartMemoryStreamProvider(); await Request.Content.ReadAsMultipartAsync(provider); // extract file name and file contents var fileNameParam = provider.Contents[0].Headers.ContentDisposition.Parameters .FirstOrDefault(p => p.Name.ToLower() == "filename"); string fileName = (fileNameParam == null) ? "" : fileNameParam.Value.Trim('"'); byte[] file = await provider.Contents[0].ReadAsByteArrayAsync(); // Here you can use EF with an entity with a byte[] property, or // an stored procedure with a varbinary parameter to insert the // data into the DB var result = string.Format("Received '{0}' with length: {1}", fileName, file.Length); return result; } } 

第三,默认情况下,最大上传大小是有限的。 您可以克服修改web.config这些限制:

  1. 添加maxRequestLength="max size in bytes" 。 (如果它不存在,则创建此lement):

  2. maxAllowedContentLength添加到元素(如果该元素不存在,则创建此元素)

这些条目如下所示:

           

注意:您应该将其包含在元素中,以便此限制仅应用于上载文件的特定路由,如下所示:

   ...  ... 

注意修改根web.config ,而不是Views文件夹中的那个。

第四,关于在数据库中保存数据,如果使用EF,则只需要这样的实体:

 public class File { public int FileId { get; set; } public string FileName { get; set; } public byte[] FileContent { get; set; } } 

创建此类的新对象,添加到上下文并保存更改。

如果使用存储过程,请创建一个具有varbinary参数的存储过程,并将byte[] file作为值传递。

使用webAPI控制器执行此操作的更简洁方法如下:

创建一个web api控制器文件: UploadFileController.cs

 public class UploadFileController : ApiController { // POST api/ public HttpResponseMessage Post() { HttpResponseMessage result = null; var httpRequest = HttpContext.Current.Request; if (httpRequest.Files.Count > 0) { var docfiles = new List(); foreach (string file in httpRequest.Files) { var postedFile = httpRequest.Files[file]; int hasheddate = DateTime.Now.GetHashCode(); //Good to use an updated name always, since many can use the same file name to upload. string changed_name = hasheddate.ToString() + "_" + postedFile.FileName; var filePath = HttpContext.Current.Server.MapPath("~/Images/" + changed_name); postedFile.SaveAs(filePath); // save the file to a folder "Images" in the root of your app changed_name = @"~\Images\" + changed_name; //store this complete path to database docfiles.Add(changed_name); } result = Request.CreateResponse(HttpStatusCode.Created, docfiles); } else { result = Request.CreateResponse(HttpStatusCode.BadRequest); } return result; } } 

在标记中使用此webAPI。 使用以下:

    

您可以在输入标记的“accept”属性中更改文件类型(要接受的扩展名)。 希望它会有所帮助! 请享用!

如果要将文件保存到数据库中的BLOB字段,则可以使用以下post中提供的代码:将任何文件保存到数据库中,只需将其转换为字节数组即可? 。

相关代码如下:

 public static int databaseFilePut(MemoryStream fileToPut) { int varID = 0; byte[] file = fileToPut.ToArray(); const string preparedCommand = @" INSERT INTO [dbo].[Raporty] ([RaportPlik]) VALUES (@File) SELECT [RaportID] FROM [dbo].[Raporty] WHERE [RaportID] = SCOPE_IDENTITY() "; using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) { sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file; using (var sqlWriteQuery = sqlWrite.ExecuteReader()) while (sqlWriteQuery != null && sqlWriteQuery.Read()) varID = sqlWriteQuery["RaportID"] is int ? (int) sqlWriteQuery["RaportID"] : 0; } return varID; } 

您可以将您发送的链接中的方法与用于提交MemoryStream的代码组合到我链接到的答案中提供的数据库中。

您需要在表中使用特定列来保存实际文件名。 基本上,您需要文件内容的BLOB列和文件名的另一个TEXTVARCHAR列。 您提供的链接显示了获取文件名称的方法。

但是,正如其他人指出的那样,您不应该将文件保存到数据库中。 处理文件上载的最常用方法是将它们保存到服务器上的某个位置,并将保存文件的路径提交到数据库中的TEXTVARCHAR字段。

您无法直接将文件保存到数据库。

除了在本地保存文件之外,其中一个选项是将其保存到内存流中,然后将其传递给数据库。 这个问题可以为您提供如何获取文件名和扩展名并将文件保存到内存中的代码示例: Web API:如何在使用MultipartMemoryStreamProvider时访问多部分表单值?

我认为你想在这里实现的目标在前一个问题中得到了部分回答

现在,关于直接保存到数据库,你应该能够实现这一点,而不是首先将文件保存到硬盘驱动器,通常是通过获取流字节数组并将其作为byte []放入数据库实体或行属性(数组)字节)