ASP.NET Web API'sinde HTML Form Verileri Gönderme: Dosya Yükleme ve Çok Bölümlü MIME
Bölüm 2: Dosya Yükleme ve Çok Parçalı MIME
Bu öğreticide bir web API'sine nasıl dosya yüklendiği gösterilir. Ayrıca çok parçalı MIME verilerinin nasıl işlendiği de açıklanır.
Aşağıda, dosyayı karşıya yüklemek için bir HTML formu örneği verilmiştir:
<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>
Bu form bir metin girişi denetimi ve bir dosya girişi denetimi içerir. Form bir dosya giriş denetimi içerdiğinde, enctype özniteliği her zaman formun çok parçalı bir MIME iletisi olarak gönderileceğini belirten "çok parçalı/form-veri" olmalıdır.
Çok parçalı BIR MIME iletisinin biçimini anlamak için örnek bir isteğe göz atabilirsiniz:
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--
Bu ileti, her form denetimi için bir tane olmak üzere iki bölüme ayrılır. Parça sınırları tirelerle başlayan çizgilerle gösterilir.
Not
Parça sınırı, sınır dizesinin yanlışlıkla ileti parçası içinde görünmemesini sağlamak için rastgele bir bileşen ("41184676334") içerir.
Her ileti bölümü bir veya daha fazla üst bilgi ve ardından bölüm içeriği içerir.
- Content-Disposition üst bilgisi denetimin adını içerir. Dosyalar için dosya adını da içerir.
- content-type üst bilgisi bölümdeki verileri açıklar. Bu üst bilgi atlanırsa, varsayılan değer metin/düz olur.
Önceki örnekte kullanıcı, image/jpeg içerik türüne sahip GrandCanyon.jpg adlı bir dosyayı karşıya yükledi; ve metin girişinin değeri "Yaz Tatili" idi.
Dosya Karşıya Yükleme
Şimdi çok parçalı bir MIME iletisindeki dosyaları okuyan bir Web API denetleyicisine bakalım. Denetleyici dosyaları zaman uyumsuz olarak okur. Web API'si , görev tabanlı programlama modelini kullanarak zaman uyumsuz eylemleri destekler. İlk olarak, async ve await anahtar sözcüklerini destekleyen .NET Framework 4.5'i hedefliyorsanız kod aşağıdadır.
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);
}
}
}
Denetleyici eyleminin herhangi bir parametre almadığını göreceksiniz. Bunun nedeni, bir medya türü biçimlendirici çağırmadan eylemin içindeki istek gövdesini işlememizdir.
IsMultipartContent yöntemi, isteğin çok parçalı bir MIME iletisi içerip içermediğini denetler. Aksi takdirde denetleyici HTTP durum kodu 415 'i (Desteklenmeyen Medya Türü) döndürür.
MultipartFormDataStreamProvider sınıfı, karşıya yüklenen dosyalar için dosya akışlarını ayıran bir yardımcı nesnedir. Çok parçalı MIME iletisini okumak için ReadAsMultipartAsync yöntemini çağırın. Bu yöntem tüm ileti bölümlerini ayıklar ve MultipartFormDataStreamProvider tarafından sağlanan akışlara yazar.
Yöntem tamamlandığında, MultipartFileData nesnelerinin bir koleksiyonu olan FileData özelliğinden dosyalar hakkında bilgi alabilirsiniz.
- MultipartFileData.FileName , dosyanın kaydedildiği sunucudaki yerel dosya adıdır.
- MultipartFileData.Headers , parça üst bilgisini (istek üst bilgisini değil ) içerir. Content_Disposition ve İçerik Türü üst bilgilerine erişmek için bunu kullanabilirsiniz.
Adından da anlaşılacağı gibi ReadAsMultipartAsync zaman uyumsuz bir yöntemdir. Yöntem tamamlandıktan sonra çalışma gerçekleştirmek için bir devamlılık görevi (.NET 4.0) veya await anahtar sözcüğünü (.NET 4.5) kullanın.
Önceki kodun .NET Framework 4.0 sürümü aşağıdadır:
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;
}
Form Denetim Verilerini Okuma
Daha önce gösterdiğim HTML formunda metin girişi denetimi vardı.
<div>
<label for="caption">Image Caption</label>
<input name="caption" type="text" />
</div>
Denetimin değerini MultipartFormDataStreamProvider'ınFormData özelliğinden alabilirsiniz.
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 , form denetimleri için ad/değer çiftleri içeren bir NameValueCollection'dır . Koleksiyon yinelenen anahtarlar içerebilir. Şu formu göz önünde bulundurun:
<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>
İstek gövdesi şöyle görünebilir:
-----------------------------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--
Bu durumda , FormData koleksiyonu aşağıdaki anahtar/değer çiftlerini içerir:
- seyahat: gidiş dönüş
- seçenekler: kesintisiz
- seçenekler: tarihler
- koltuk: pencere
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin