2015-01-09 3 views
5

Я хочу загрузить файл с помощью WebApi, сделав ajax-вызов, и файл будет сохранен в базе данных. Я попробовал код, указанный в this link. Здесь он сохраняет полученные данные на жесткий диск в виде файла без указанного расширения, но я хочу сделать что-то вроде, когда я сохраняю файл в базе данных. Я также хочу сохранить имя файла и причину расширения позже, если мне нужно для загрузки файла я могу указать имя файла и его расширение. И в ссылке файл сохраняется на жесткий диск в виде файла, но есть ли способ, которым я могу напрямую сохранить файл в DB.Загрузить файл с помощью WebApi, ajax

+1

Это очень трудно прочитать это сообщение ... Не могли бы вы переписать его? Попробуйте использовать короткие отсрочки. – IAfanasov

+0

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

ответ

11

Ответ имеет несколько частей.

Во-первых, чтобы загрузить файл, вы можете использовать представление с кодом вроде этого:

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

Во-вторых, чтобы получить эти данные, создать контроллер, с помощью метода, как это:

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

В-третьих, по умолчанию максимальный размер загрузки ограничен. Вы можете преодолеть эти ограничения, изменяющие web.config:

  1. Добавить maxRequestLength="max size in bytes" в <configuration><system.web><httpRuntime>. (Или создать этот lement, если он не существует):

  2. maxAllowedContentLength Добавить в <configuration><system.web><security><requestFiltering><requestLimits> элемент (или создать этот элемент, если он не существует)

Эти записи выглядят следующим образом:

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

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

Опасайтесь изменить корень 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.

0

Вы не можете напрямую сохранить файл в базу данных.

Один из вариантов, помимо сохранения локального файла, сохраняет его в потоке памяти и затем передает его в базу данных. Этот вопрос может дать вам пример кода, как вы можете получить имя файла и расширение, и сохраните файл в память: Web API: how to access multipart form values when using MultipartMemoryStreamProvider?

0

Я думаю, что вы хотите достичь здесь частично ответить в этом previous question

Теперь, о сохранении непосредственно в базе данных, вы должны добиться этого, не сохраняя файл на жестком диске, обычно, беря массив байтов потока и помещая его в свой объект базы данных или свойство строки в виде байта [] (массив байтов)

1

уборщик способ сделать это с помощью контроллера WebAPI выглядит следующим образом:

Создать веб-файл контроллера апи: 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; 
    } 
} 

Чтобы использовать эту WebAPI в разметке. Используйте следующее:

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

Вы можете изменить тип файла (расширения, чтобы принять) в «Accept» атрибут тега ввода. Надеюсь, это поможет! Наслаждайтесь!

+1

Почему вы считаете это чище? Вы используете HttpContext.Current и ищете конкретную переменную сервера через строку. И почему вы получаете хэшированный DateTime.Now и берут первые 4 из этого. Кажется дорогостоящим способом создания имени. – MPavlak

+0

@MPavlak Обе эти вещи были специфичны для требования в моем коде. Я согласен, они должны/не должны использоваться всеми. Я обновляю свой ответ. Спасибо, что указал. – vohrahul

1

Если вы хотите сохранить файл в поле BLOB в вашей базе данных, то вы можете использовать код, указанный в следующем сообщении: Saving any file to in the database, just convert it to a byte array?.

Соответствующий код приведен ниже:

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 для содержимого файла и еще один столбец TEXT или VARCHAR для имени файла. Указанная ссылка показывает способ получения имени файла.

Однако, как указывали другие, вы не должны сохранять файлы в базе данных. Наиболее распространенным способом обработки загрузки файлов является сохранение их в определенном месте на сервере и передача пути к сохраненному файлу в поле или VARCHAR в базе данных.

Смежные вопросы