2015-01-09 14 views
5

Desidero caricare il file utilizzando un WebApi effettuando una chiamata ajax e il file verrà salvato nel database. Ho provato il codice indicato nello this link. Qui, vengono salvati i dati ricevuti sul disco rigido come un file senza estensione specificata ma voglio fare qualcosa di simile quando sto salvando il file nel database Voglio anche salvare il nome del file e l'estensione causerà in seguito se ho bisogno per scaricare il file posso fornire il nome del file e l'estensione con esso. E nel collegamento il file viene salvato sul disco rigido come un file, ma c'è un modo in cui posso salvare direttamente il file in DB.Carica file utilizzando WebApi, ajax

+1

è davvero difficile leggere questo messaggio ... potresti riscriverlo? Prova a usare sentenze brevi. – IAfanasov

+0

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

risposta

11

La risposta ha diverse parti.

In primo luogo, per caricare il file, è possibile utilizzare una vista con codice come questo:

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

In secondo luogo, per ricevere questi dati, creare un controllore, con un metodo come questo:

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

In terzo luogo, per impostazione predefinita la dimensione massima di caricamento è limitata. È possibile superare queste limitazioni modifica web.config:

  1. Aggiungi maxRequestLength="max size in bytes" in <configuration><system.web><httpRuntime>. (O creare questa lement se non esiste):

  2. Aggiungi maxAllowedContentLength-<configuration><system.web><security><requestFiltering><requestLimits> elemento (o creare questo elemento se non esiste)

Queste voci appaiono così:

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

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

Attenzione a modificare la radice web.config, non quella nella cartella Views.

In quarto luogo, per quanto riguarda il salvataggio dei dati nel database, se si utilizza EF, è sufficiente un soggetto come questo:

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

creare un nuovo oggetto di questa classe, aggiungere al contesto e salvare le modifiche .

Se si utilizzano stored procedure, crearne una che abbia un parametro varbinary e passare il valore byte[] file come valore.

0

Penso che ciò che si vuole raggiungere qui è in parte una risposta in questo previous question

Ora, riguardo al salvataggio diretto nel database, dovresti essere in grado di ottenere ciò senza prima salvare il file su un disco rigido, normalmente prendendo l'array di byte del flusso e inserendolo nell'entità del database o nella proprietà della riga come byte [] (array di byte)

1

un modo più pulito per fare questo controller WebAPI utilizzando è il seguente:

Creare un file di controllo Web 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; 
    } 
} 

Per utilizzare questa WebAPI nel markup. Utilizzare i seguenti:

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

È possibile modificare il tipo di file (estensioni di accettare) nella attributo "accetta" del tag input. Spero che possa aiutarti! Godere!

+1

Perché consideri questo detergente? Stai utilizzando HttpContext.Current e stai cercando una specifica variabile del server tramite stringa. E perché stai ricevendo un hash DateTime.Ora e prendendo il primo 4 di questo. Sembra un modo costoso per generare un nome. – MPavlak

+0

@MPavlak Entrambe le due cose erano specifiche per un requisito nel mio codice. Sono d'accordo, questi dovrebbero/non essere usati da tutti. Sto aggiornando la mia risposta. Grazie per aver indicato. – vohrahul

1

Se si desidera salvare il file in un campo BLOB nel database, è possibile utilizzare il codice fornito nel seguente post: Saving any file to in the database, just convert it to a byte array?.

Il codice in questione è qui sotto:

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

È possibile combinare l'approccio nel link che hai inviato con il codice per aver commesso un MemoryStream al database fornito in una risposta ho collegato.

Avrete bisogno di una colonna specifica nella vostra tabella per salvare il nome del file attuale. Fondamentalmente, avrete bisogno di una colonna BLOB per il contenuto del file e un'altra colonna TEXT o VARCHAR per il nome del file. Il link che hai fornito mostra un modo per ottenere il nome del file.

Tuttavia, come altri hanno sottolineato, non è necessario salvare i file nel database. Il modo più comune di gestire i caricamenti di file è di salvarli in qualche posizione sul server e impegnare il percorso del file salvato in un campo TEXT o VARCHAR nel database.

Problemi correlati