2015-01-09 15 views
5

Tôi muốn tải tệp lên bằng WebApi bằng cách thực hiện cuộc gọi ajax và tệp sẽ lưu vào cơ sở dữ liệu. Tôi đã thử mã được cung cấp trong số this link. Ở đây, nó được lưu dữ liệu đã nhận vào ổ cứng dưới dạng tệp không có phần mở rộng được chỉ định nhưng tôi muốn làm một cái gì đó như khi tôi lưu tệp vào Cơ sở dữ liệu Tôi cũng muốn lưu tên tệp và nguyên nhân mở rộng sau này nếu tôi cần để tải xuống tệp, tôi có thể cung cấp tên tệp và phần mở rộng với tệp đó. Và trong liên kết tệp được lưu vào ổ cứng dưới dạng tệp nhưng có cách nào để tôi có thể lưu tệp trực tiếp vào DB.Tải tệp lên bằng WebApi, ajax

+1

thật sự rất khó đọc tin nhắn này ... Bạn có thể viết lại không? Hãy thử sử dụng các cảm xúc ngắn. – IAfanasov

+0

http://www.codeproject.com/Articles/806075/File-Upload-using-jQuery-AJAX-in-ASP-NET-Web-API – Greg

Trả lời

11

Câu trả lời có một số phần.

Trước tiên, để tải lên các tập tin, bạn có thể sử dụng một cái nhìn với mã như thế này:

@using (Html.BeginForm()) 
{ 
    <input type="file" value="Choose a file"/> 
    <br/> 
    <input type="button" value="Upload" id="upload"/> 
} 

@section scripts 
{ 
<script type="text/javascript"> 
    $(document).ready(function() { 
     $('#upload').click(function() { 
      var data = new FormData(); 
      var file = $('form input[type=file]')[0].files[0]; 
      data.append('file',file); 
      $.ajax({ 
       url: '/Api/File/Upload', 
       processData: false, 
       contentType: false, 
       data: data, 
       type: 'POST' 
      }).done(function(result) { 
       alert(result); 
      }).fail(function(a, b, c) { 
       console.log(a, b, c); 
      }); 
     }); 
    }); 
</script>  
} 

Thứ hai, để nhận dữ liệu này, tạo ra một bộ điều khiển, với một phương pháp như thế này:

public class FileController : ApiController 
{ 
    [HttpPost] 
    public async Task<string> 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; 
    } 
} 

Thứ ba, theo mặc định, kích thước tải lên tối đa bị giới hạn. Bạn có thể khắc phục được những hạn chế này điều chỉnh web.config:

  1. Thêm maxRequestLength="max size in bytes" trong <configuration><system.web><httpRuntime>. (Hoặc tạo lement này nếu nó không tồn tại):

  2. Thêm maxAllowedContentLength-<configuration><system.web><security><requestFiltering><requestLimits> yếu tố (hoặc tạo yếu tố này nếu nó không tồn tại)

Những mục trông như thế này:

<configuration> 
    <system.web> 
    <httpRuntime targetFramework="4.5" maxRequestLength="2000000000" /> 

<configuration> 
    <system.web> 
    <security> 
    <requestFiltering> 
     <requestLimits maxAllowedContentLength="2000000000"/> 

Cẩn thận sửa đổi thư mục gốc web.config, không phải thư mục gốc trong thư mục Views.

Thứ tư, như để lưu dữ liệu trong cơ sở dữ liệu, nếu bạn sử dụng EF, bạn chỉ cần một tổ chức như thế này:

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

Tạo một đối tượng mới của lớp này, thêm vào bối cảnh và lưu thay đổi .

Nếu bạn sử dụng quy trình được lưu trữ, hãy tạo một tham số có thông số varbinary và chuyển giá trị byte[] file làm giá trị.

0

Bạn không thể lưu trực tiếp tệp vào cơ sở dữ liệu.

Một trong các tùy chọn, ngoài việc lưu tệp cục bộ, lưu nó vào luồng bộ nhớ và sau đó chuyển nó vào cơ sở dữ liệu. Câu hỏi này có thể cung cấp cho bạn mã ví dụ về cách bạn có thể nhận được các tên tập tin và mở rộng và lưu các tập tin vào bộ nhớ: Web API: how to access multipart form values when using MultipartMemoryStreamProvider?

0

Tôi nghĩ rằng những gì bạn muốn đạt được ở đây là phần trả lời trong này previous question

Bây giờ, về việc lưu trực tiếp vào cơ sở dữ liệu, bạn có thể đạt được điều này mà không lưu tệp vào ổ cứng trước, thường bằng cách lấy mảng byte luồng và đặt nó vào thực thể cơ sở dữ liệu hoặc thuộc tính hàng dưới dạng byte [] (mảng byte)

1

Một cách sạch để làm sử dụng bộ điều khiển WebAPI này là như sau:

Tạo một trang web tập tin điều khiển api: UploadFileController.cs

public class UploadFileController : ApiController 
{ 
    // POST api/<controller> 
    public HttpResponseMessage Post() 
    { 
     HttpResponseMessage result = null; 
     var httpRequest = HttpContext.Current.Request; 
     if (httpRequest.Files.Count > 0) 
     { 
      var docfiles = new List<string>(); 
      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; 
    } 
} 

Để sử dụng WebAPI này trong đánh dấu của bạn. Sử dụng như sau:

<input type="hidden" id="insertPicture" /> 
<input id="insertFileupload" type="file" name="files[]" accept="image/*" data-url="/api/uploadfile" multiple> 
<script> 
$(function() { 
$('#insertFileupload').fileupload({ 
    add: function (e, data) { 
    var jqXHR = data.submit() 
     .success(function (result, textStatus, jqXHR) {/* ... */ 
      $('#insertPicture').val(result); 
      alert("File Uploaded"); 
     }) 
     .error(function (jqXHR, textStatus, errorThrown) {/* ... */ 
      alert(errorThrown); 
     }) 
    } 
    }); 
}); 

Bạn có thể thay đổi kiểu tập tin (phần mở rộng để chấp nhận) trong "chấp nhận" thuộc tính của thẻ đầu vào. Hy vọng nó sẽ giúp bạn! Thưởng thức!

+1

Tại sao bạn xem xét công cụ dọn dẹp này? Bạn đang sử dụng HttpContext.Current và tìm kiếm một biến máy chủ cụ thể thông qua chuỗi. Và tại sao bạn nhận được một DateTime.Now băm và lấy 4 đầu tiên trong số đó. Có vẻ như cách đắt tiền để tạo ra một cái tên. – MPavlak

+0

@MPavlak Cả hai thứ đều cụ thể cho một yêu cầu trong mã của tôi. Tôi đồng ý, những/nên không được sử dụng bởi tất cả mọi người. Tôi đang cập nhật câu trả lời của mình. Cảm ơn bạn đã trỏ. – vohrahul

1

Nếu bạn muốn lưu tệp vào trường BLOB trong cơ sở dữ liệu của mình, khi đó bạn có thể sử dụng mã được cung cấp trong bài đăng sau: Saving any file to in the database, just convert it to a byte array?.

Mã liên quan là dưới đây:

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; 
} 

Bạn có thể kết hợp phương pháp này trong liên kết mà bạn gửi kèm theo mã cho phạm MemoryStream cơ sở dữ liệu được cung cấp trong một câu trả lời tôi liên kết với.

Bạn sẽ cần cột cụ thể trong bảng của mình để lưu tên tệp thực. Về cơ bản, bạn sẽ cần một cột BLOB cho nội dung tệp và một cột TEXT hoặc VARCHAR khác cho tên tệp. Liên kết bạn cung cấp cho biết cách lấy tên của tệp.

Tuy nhiên, như những người khác đã chỉ ra, bạn không nên lưu tệp vào cơ sở dữ liệu. Cách phổ biến nhất để xử lý tải lên tệp là lưu chúng vào một số vị trí trên máy chủ và cam kết đường dẫn đến tệp đã lưu vào trường TEXT hoặc VARCHAR trong cơ sở dữ liệu.

Các vấn đề liên quan