Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Část 2: Nahrávání souborů a vícedílné mime
V tomto kurzu se dozvíte, jak nahrát soubory do webového rozhraní API. Popisuje také, jak zpracovávat data MIME s více částmi.
Poznámka
Tady je příklad formuláře HTML pro nahrání souboru:
<form name="form1" method="post" enctype="multipart/form-data" action="api/upload">
<div>
<label for="caption">Image Caption</label>
<input name="caption" type="text" />
</div>
<div>
<label for="image1">Image File</label>
<input name="image1" type="file" />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
Tento formulář obsahuje ovládací prvek textového zadání a ovládací prvek pro zadávání souborů. Pokud formulář obsahuje ovládací prvek vstupu souboru, atribut enctype by měl být vždy "multipart/form-data", který určuje, že formulář bude odeslán jako zpráva MIME s více částmi.
Formát zprávy MIME s více částmi je nejsnadnější, když se podíváte na příklad požadavku:
POST http://localhost:50460/api/values/1 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------41184676334
Content-Length: 29278
-----------------------------41184676334
Content-Disposition: form-data; name="caption"
Summer vacation
-----------------------------41184676334
Content-Disposition: form-data; name="image1"; filename="GrandCanyon.jpg"
Content-Type: image/jpeg
(Binary data not shown)
-----------------------------41184676334--
Tato zpráva je rozdělena na dvě části, jednu pro každý ovládací prvek formuláře. Hranice částí jsou označeny čarami, které začínají pomlčkami.
Poznámka
Hranice části obsahuje náhodnou komponentu ("41184676334"), aby se zajistilo, že se řetězec ohraničení nechtěně nezobrazí uvnitř části zprávy.
Každá část zprávy obsahuje jedno nebo více záhlaví následovaných obsahem části.
- Hlavička Content-Disposition obsahuje název ovládacího prvku. U souborů obsahuje také název souboru.
- Hlavička Content-Type popisuje data v části. Pokud je toto záhlaví vynecháno, výchozí hodnota je text/prostý text.
V předchozím příkladu uživatel nahrál soubor s názvem GrandCanyon.jpg s typem obsahu image/jpeg; a hodnota textového zadání byla "Letní dovolená".
Nahrání souboru
Teď se podívejme na kontroler webového rozhraní API, který čte soubory ze zprávy MIME s více částmi. Kontroler bude soubory číst asynchronně. Webové rozhraní API podporuje asynchronní akce pomocí programovacího modelu založeného na úlohách. Nejprve je zde kód, pokud cílíte na rozhraní .NET Framework 4.5, které podporuje async a await klíčová slova.
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
public class UploadController : ApiController
{
public async Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the file names.
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine(file.Headers.ContentDisposition.FileName);
Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
}
Všimněte si, že akce kontroleru nepřebírají žádné parametry. Je to proto, že zpracováváme text požadavku uvnitř akce, aniž bychom museli vyvolat formátovací modul typu média.
Metoda IsMultipartContent kontroluje, jestli požadavek obsahuje zprávu MIME s více částmi. Pokud ne, vrátí kontroler stavový kód HTTP 415 (nepodporovaný typ média).
MultipartFormDataStreamProvider Třída je pomocný objekt, který přiděluje datové proudy souborů pro nahrané soubory. Pokud chcete přečíst zprávu MIME s více částmi, zavolejte metodu ReadAsMultipartAsync . Tato metoda extrahuje všechny části zprávy a zapisuje je do datových proudů poskytovaných MultipartFormDataStreamProvider.
Po dokončení metody můžete získat informace o souborech z FileData vlastnost, což je kolekce MultipartFileData objektů.
- MultipartFileData.FileName je název místního souboru na serveru, na kterém byl soubor uložen.
- MultipartFileData.Headers obsahuje hlavičku části (ne hlavičku požadavku). Můžete ho použít pro přístup k hlavičce Content_Disposition a Content-Type.
Jak název napovídá, ReadAsMultipartAsync je asynchronní metoda. Pokud chcete provést práci po dokončení metody, použijte úlohu pokračování (.NET 4.0) nebo klíčové slovo await (.NET 4.5).
Tady je verze .NET Framework 4.0 předchozího kódu:
public Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
// Read the form data and return an async task.
var task = Request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
}
// This illustrates how to get the file names.
foreach (MultipartFileData file in provider.FileData)
{
Trace.WriteLine(file.Headers.ContentDisposition.FileName);
Trace.WriteLine("Server file path: " + file.LocalFileName);
}
return Request.CreateResponse(HttpStatusCode.OK);
});
return task;
}
Čtení dat ovládacího prvku formuláře
Formulář HTML, který jsem zobrazil dříve, měl ovládací prvek textového zadávání.
<div>
<label for="caption">Image Caption</label>
<input name="caption" type="text" />
</div>
Můžete získat hodnotu ovládacího prvku z FormData vlastnost MultipartFormDataStreamProvider.
public async Task<HttpResponseMessage> PostFormData()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
await Request.Content.ReadAsMultipartAsync(provider);
// Show all the key-value pairs.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
Trace.WriteLine(string.Format("{0}: {1}", key, val));
}
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
FormData je NameValueCollection , která obsahuje páry název/hodnota pro ovládací prvky formuláře. Kolekce může obsahovat duplicitní klíče. Zvažte tento formulář:
<form name="trip_search" method="post" enctype="multipart/form-data" action="api/upload">
<div>
<input type="radio" name="trip" value="round-trip"/>
Round-Trip
</div>
<div>
<input type="radio" name="trip" value="one-way"/>
One-Way
</div>
<div>
<input type="checkbox" name="options" value="nonstop" />
Only show non-stop flights
</div>
<div>
<input type="checkbox" name="options" value="airports" />
Compare nearby airports
</div>
<div>
<input type="checkbox" name="options" value="dates" />
My travel dates are flexible
</div>
<div>
<label for="seat">Seating Preference</label>
<select name="seat">
<option value="aisle">Aisle</option>
<option value="window">Window</option>
<option value="center">Center</option>
<option value="none">No Preference</option>
</select>
</div>
</form>
Text požadavku může vypadat takto:
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="trip"
round-trip
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="options"
nonstop
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="options"
dates
-----------------------------7dc1d13623304d6
Content-Disposition: form-data; name="seat"
window
-----------------------------7dc1d13623304d6--
V takovém případě by kolekce FormData obsahovala následující páry klíč/hodnota:
- trip: round-trip
- možnosti: nonstop
- možnosti: data
- sedadlo: okno