[WebApi] 搗鼓一個資源管理員--多檔案上傳,webapi搗鼓
《打造一個網站或者其他網路應用的檔案管理介面(WebApi)第二章“多檔案上傳”》
========================================================
作者:qiujuer
部落格:blog.csdn.net/qiujuer
網站:www.qiujuer.net
開源庫:Genius-Android
轉載請註明出處:http://blog.csdn.net/qiujuer/article/details/41675299
========================================================
History
[WebApi] 搗鼓一個資源管理員--檔案下載
In This
既然訪問檔案介面有了,怎麼能少的了檔案的上傳介面呢!
既然是檔案上傳介面那就肯定要來一個猛一點的介面--多檔案上傳
CodeTime改動
進入正題前先來看看本次改動的檔案有哪些:
可以看見一共有4個檔案進行了改動,其中Home與ResourceApi是添加了方法,Model/Resource是新增,View/Upload也是新增。
Model部分
為了返回資料簡單方便,所以New 了一個類 Resource.cs
namespace WebResource.Models{ public class Resource { public string Id { get; set; } public string Type { get; set; } }}If Easy?
ResourceApi 部分
然後來看看咱們的ResourceApi類:
namespace WebResource.Controllers{ [RoutePrefix("Resource")] public class ResourceApiController : ApiController { private static readonly long MEMORY_SIZE = 64 * 1024 * 1024; private static readonly string ROOT_PATH = HttpContext.Current.Server.MapPath("~/App_Data/"); [HttpGet] [Route("{Id}")] public async Task<HttpResponseMessage> Get(string Id) { // 進入時判斷當前請求中是否含有 ETag 標識,如果有就返回使用瀏覽器緩衝 // Return 304 var tag = Request.Headers.IfNoneMatch.FirstOrDefault(); if (Request.Headers.IfModifiedSince.HasValue && tag != null && tag.Tag.Length > 0) return new HttpResponseMessage(HttpStatusCode.NotModified); // 進行類比 App_Data/Image/{id}.png // 開啟找到檔案 FileInfo info = new FileInfo(Path.Combine(ROOT_PATH, "Image", Id + ".png")); if (!info.Exists) return new HttpResponseMessage(HttpStatusCode.BadRequest); FileStream file = null; try { // 開啟檔案 file = new FileStream(info.FullName, FileMode.Open, FileAccess.Read, FileShare.Read); HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); // 在瀏覽器中顯示 inline ContentDispositionHeaderValue disposition = new ContentDispositionHeaderValue("inline"); // 寫入檔案基本資料 disposition.FileName = file.Name; disposition.Name = file.Name; disposition.Size = file.Length; // 判斷是否大於64Md,如果大於就採用分段流返回,否則直接返回 if (file.Length < MEMORY_SIZE) { //Copy To Memory And Close. byte[] bytes = new byte[file.Length]; await file.ReadAsync(bytes, 0, (int)file.Length); file.Close(); MemoryStream ms = new MemoryStream(bytes); result.Content = new ByteArrayContent(ms.ToArray()); } else { result.Content = new StreamContent(file); } // 寫入檔案類型,這裡是圖片png result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png"); result.Content.Headers.ContentDisposition = disposition; // 設定緩衝資訊,該部分可以沒有,該部分主要是用於與開始部分結合以便瀏覽器使用304緩衝 // Set Cache result.Content.Headers.Expires = new DateTimeOffset(DateTime.Now).AddHours(1); // 這裡應該寫入檔案的儲存日期 result.Content.Headers.LastModified = new DateTimeOffset(DateTime.Now); result.Headers.CacheControl = new CacheControlHeaderValue() { Public = true, MaxAge = TimeSpan.FromHours(1) }; // 設定Etag,這裡就簡單採用 Id result.Headers.ETag = new EntityTagHeaderValue(string.Format("\"{0}\"", Id)); // 返回請求 return result; } catch { if (file != null) { file.Close(); } } return new HttpResponseMessage(HttpStatusCode.BadRequest); } [HttpPost] [Route("Upload")] [ResponseType(typeof(Resource))] public async Task<IHttpActionResult> Post() { List<Resource> resources = new List<Resource>(); // multipart/form-data // 採用MultipartMemoryStreamProvider var provider = new MultipartMemoryStreamProvider(); //讀取檔案資料 await Request.Content.ReadAsMultipartAsync(provider); foreach (var item in provider.Contents) { // 判斷是否是檔案 if (item.Headers.ContentDisposition.FileName != null) { //擷取到流 var ms = item.ReadAsStreamAsync().Result; //進行流操作 using (var br = new BinaryReader(ms)) { if (ms.Length <= 0) break; //讀取檔案內容到記憶體中 var data = br.ReadBytes((int)ms.Length); //Create //目前時間作為ID Resource resource = new Resource() { Id = DateTime.Now.ToString("yyyyMMddHHmmssffff", DateTimeFormatInfo.InvariantInfo) }; //Info FileInfo info = new FileInfo(item.Headers.ContentDisposition.FileName.Replace("\"", "")); //檔案類型 resource.Type = info.Extension.Substring(1).ToLower(); //Write try { //檔案儲存體地址 string dirPath = Path.Combine(ROOT_PATH); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } File.WriteAllBytes(Path.Combine(dirPath, resource.Id), data); resources.Add(resource); } catch { } } } } //返回 if (resources.Count == 0) return BadRequest(); else if (resources.Count == 1) return Ok(resources.FirstOrDefault()); else return Ok(resources); } }}與上一章比較看來,只是增加了一個方法 Post ,而後將其重新導向為
Resource/Upload
其中主要幹了些什麼我都在方法中註明了;應該是足夠簡單的。
現在運行一下,看看我們的Api是怎樣的:
下面我們來調用它試試。
HomeController部分
修改HomeController 添加一個Upload 方法:
namespace WebResource.Controllers{ public class HomeController : Controller { public ActionResult Index() { ViewBag.Title = "Home Page"; return View(); } public ActionResult Upload() { return View(); } }}
Upload.cshtml部分而後在方法上點擊右鍵添加視圖,然後進入
View/Home/Upload.cshtml 視圖中修改為:
@{ ViewBag.Title = "Upload";}<h2>Upload</h2><div id="body"> <h1>多檔案上傳模式</h1> <section class="main-content clear-fix"> <form name="form1" method="post" enctype="multipart/form-data" action="/Resource/Upload"> <fieldset> <legend>File Upload Example</legend> <div> <label for="caption">File1</label> <input name="file1" type="file" /> </div> <div> <label for="image1">File2</label> <input name="file2" type="file" /> </div> <div> <input type="submit" value="Submit" /> </div> </fieldset> </form> </section></div>在該視圖中,我們建立了一個
Form 表單,然後指定為
Post 模式;同時指定
enctype="multipart/form-data" action="/Resource/Upload"
RunTime
寫完了代碼當然是調試運行嘍!
運行 localhost:60586/Home/Upload
這裡我們添加檔案,還是使用上一章中的兩種圖片吧:
運行後:
當然,這裡是因為我的瀏覽器是Google瀏覽器,所以返回的是 XML 資料,如果你的事IE瀏覽器那麼應該返回的是Json 檔案。
WebApi會根據請求返回不同的資料。
可以看到,現在 App_Data檔案夾下,多了兩個檔案了;不過這兩個檔案是沒有加上檔案類型的;你可以手動給他加上個.png 然後開啟看看是不是那兩張圖片。
END
OK,這一章就到此為止了!
資源檔
第一章資源檔(說好了這章中添加)
第二章資源檔
下一章
下一章將會把上傳與下載查看兩個方法相互結合,搭配起來;同時將會結合資料進行輔助隱藏檔資訊。
同時,會講如何避免檔案重複上傳的問題。
========================================================
作者:qiujuer
部落格:blog.csdn.net/qiujuer
網站:www.qiujuer.net
開源庫:Genius-Android
轉載請註明出處:http://blog.csdn.net/qiujuer/article/details/41675299
========================================================