在網路編程過程中需要向伺服器上傳文件。 Multipart/form-data是上傳文件的一種方式。 ...
在網路編程過程中需要向伺服器上傳文件。
Multipart/form-data是上傳文件的一種方式。
1 /// <summary> 2 /// 上傳工程文件 3 /// </summary> 4 /// <returns></returns> 5 public async Task<HttpResponseMessage> UploadProjectFile() 6 { 7 ProjectFile postData = new ProjectFile(); 8 IEnumerable<string> stringValues; 9 //獲取請求頭文件相關參數 10 Request.Headers.TryGetValues("token", out stringValues); 11 postData.token = stringValues.FirstOrDefault(); 12 13 Request.Headers.TryGetValues("uid", out stringValues); 14 postData.uid = int.Parse(stringValues.FirstOrDefault()); 15 16 Request.Headers.TryGetValues("project_id", out stringValues); 17 postData.project_id = int.Parse(stringValues.FirstOrDefault()); 18 19 Request.Headers.TryGetValues("md5", out stringValues); 20 postData.md5 = stringValues.FirstOrDefault(); 21 22 Request.Headers.TryGetValues("file_name", out stringValues); 23 postData.file_name = stringValues.FirstOrDefault(); 24 //驗證Token 25 var result = CheckToken(postData.token); 26 if (!result) 27 { 28 return CreateResponseError(401, "請求拒絕"); 29 } 30 //獲取文件名,這裡的文件名必須帶擴展名 31 string fileName = postData.file_name; 32 33 int projectId = postData.project_id; 34 //獲取應用程式的當前工作目錄 35 string rootPath = HostingEnvironment.MapPath("~/"); 36 //通過Path類的Combine方法可以合併路徑。獲取當前工程文件夾地址 37 string directoryPath = Path.Combine(rootPath, "BgerProject", projectId.ToString()); 38 //創建目錄時如果目錄已存在,則不會重新創建目錄,且不會報錯。創建目錄時會自動創建路徑中各級不存在的目錄。 39 Directory.CreateDirectory(directoryPath); 40 //獲取當前工程文件地址 41 string filePath = Path.Combine(directoryPath, fileName); 42 if (Request.Content.IsMimeMultipartContent()) 43 { 44 Dictionary<string, string> dic = new Dictionary<string, string>(); 45 var provider = new MultipartFormDataMemoryStreamProvider(); 46 47 await Request.Content.ReadAsMultipartAsync(provider); 48 foreach (var item in provider.FileContents) 49 { 50 //Trace.WriteLine(item.Headers.ContentDisposition.FileName);//獲取上傳文件實際的文件名 51 //Trace.WriteLine("Server file path: " + item.LocalFileName);//獲取上傳文件在服務上預設的文件名 52 var stream = await item.ReadAsStreamAsync(); 53 if (Path.GetExtension(item.Headers.ContentDisposition.FileName.Replace("\"", "")) == ".mp4") 54 { 55 //通過正則表達式判斷是視頻還是音頻 56 Regex regex = new Regex("voice", RegexOptions.Compiled); 57 Match m = regex.Match(item.Headers.ContentDisposition.Name.ToLower()); 58 if (m.Success) 59 { 60 //音頻直接保存處理 61 62 //判斷是否已存在該音頻 63 if (!File.Exists(filePath)) 64 { 65 using (StreamWriter sw = new StreamWriter(filePath)) 66 { 67 stream.CopyTo(sw.BaseStream); 68 sw.Flush(); 69 } 70 } 71 } 72 else 73 { 74 //視頻進行壓縮處理 75 //保存原片(如果路徑不存在,創建路徑) 76 77 using (StreamWriter sw = new StreamWriter(filePath)) 78 { 79 stream.CopyTo(sw.BaseStream); 80 sw.Flush(); 81 } 82 //壓縮並保存上傳的視頻 83 //壓縮後的存放路徑(如果路徑不存在,創建路徑) 84 ////判斷是否已存在該視頻 85 //if (!File.Exists(filePath)) 86 //{ 87 // //壓縮保存視頻 88 // if (!FFMPEGHelper.CreateNewVideo(originalFilePath, filePath)) 89 // { 90 // continue; 91 // }; 92 //} 93 } 94 } 95 else 96 { 97 //保存原片(如果路徑不存在,創建路徑) 98 99 using (StreamWriter sw = new StreamWriter(filePath)) 100 { 101 stream.CopyTo(sw.BaseStream); 102 sw.Flush(); 103 } 104 //壓縮並保存上傳的圖片 105 //壓縮後的存放路徑(如果路徑不存在,創建路徑) 106 107 ////判斷是否已存在該圖片 108 //if (!File.Exists(filePath)) 109 //{ 110 // var pxLimit = 481; 111 // //判斷是否需要壓縮 112 // System.Drawing.Image iSource = System.Drawing.Image.FromFile(originalFilePath); 113 // if (iSource.Width <= pxLimit || iSource.Height <= pxLimit) 114 // { 115 // //無需壓縮 116 // System.IO.File.Copy(originalFilePath, filePath); 117 // } 118 // else 119 // { 120 // var min = Math.Min((int)iSource.Width, (int)iSource.Height); 121 // if (min > pxLimit) 122 // { 123 // //縮放倍率 124 // var rate = (double)pxLimit / min; 125 // var width = (int)Math.Ceiling(rate * (double)iSource.Width); 126 // var height = (int)Math.Ceiling(rate * (double)iSource.Height); 127 128 // //壓縮保存圖片 129 // if (!ImageHelper.GetPicThumbnail(originalFilePath, filePath, height, width, 100)) 130 // { 131 // continue; 132 // }; 133 // } 134 // } 135 //} 136 } 137 } 138 return CreateResponse("請求成功"); 139 140 } 141 return CreateResponseError(202,"缺少MIME內容"); 142 143 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Collections.ObjectModel; 6 using System.Collections.Specialized; 7 using System.IO; 8 using System.Net.Http; 9 using System.Net.Http.Headers; 10 using System.Threading; 11 using System.Threading.Tasks; 12 13 namespace BgerServer.Models 14 { 15 /// <summary> 16 /// 與MultipartFormDataStreamProvider對應,但不將文件直接存入指定位置,而是需要自己指定數據流如何保存 17 /// </summary> 18 public class MultipartFormDataMemoryStreamProvider : MultipartStreamProvider 19 { 20 private NameValueCollection _formData = new NameValueCollection(); 21 private Collection<bool> _isFormData = new Collection<bool>(); 22 /// <summary> 23 /// 獲取文件對應的HttpContent集合,文件如何讀取由實際使用方確定,可以ReadAsByteArrayAsync,也可以ReadAsStreamAsync 24 /// </summary> 25 public Collection<HttpContent> FileContents 26 { 27 get 28 { 29 if (this._isFormData.Count != this.Contents.Count)//兩者總數不一致,認為未執行過必須的Request.Content.ReadAsMultipartAsync(provider)方法 30 { 31 throw new InvalidOperationException("System.Net.Http.HttpContentMultipartExtensions.ReadAsMultipartAsync must be called first!"); 32 } 33 return new Collection<HttpContent>(this.Contents.Where((ct, idx) => !this._isFormData[idx]).ToList()); 34 } 35 } 36 /// <summary>Gets a <see cref="T:System.Collections.Specialized.NameValueCollection" /> of form data passed as part of the multipart form data.</summary> 37 /// <returns>The <see cref="T:System.Collections.Specialized.NameValueCollection" /> of form data.</returns> 38 public NameValueCollection FormData 39 { 40 get 41 { 42 return this._formData; 43 } 44 } 45 public override async Task ExecutePostProcessingAsync() 46 { 47 for (var i = 0; i < this.Contents.Count; i++) 48 { 49 if (!this._isFormData[i])//非文件 50 { 51 continue; 52 } 53 var formContent = this.Contents[i]; 54 ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition; 55 string formFieldName = UnquoteToken(contentDisposition.Name) ?? string.Empty; 56 string formFieldValue = await formContent.ReadAsStringAsync(); 57 this.FormData.Add(formFieldName, formFieldValue); 58 } 59 } 60 public override Stream GetStream(HttpContent parent, HttpContentHeaders headers) 61 { 62 if (parent == null) 63 { 64 throw new ArgumentNullException("parent"); 65 } 66 if (headers == null) 67 { 68 throw new ArgumentNullException("headers"); 69 } 70 ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition; 71 if (contentDisposition == null) 72 { 73 throw new InvalidOperationException("Content-Disposition is null"); 74 } 75 this._isFormData.Add(string.IsNullOrEmpty(contentDisposition.FileName)); 76 return new MemoryStream(); 77 } 78 /// <summary> 79 /// 複製自 System.Net.Http.FormattingUtilities 下同名方法,因為該類為internal,不能在其它命名空間下被調用 80 /// </summary> 81 /// <param name="token"></param> 82 /// <returns></returns> 83 private static string UnquoteToken(string token) 84 { 85 if (string.IsNullOrWhiteSpace(token)) 86 { 87 return token; 88 } 89 if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1) 90 { 91 return token.Substring(1, token.Length - 2); 92 } 93 return token; 94 } 95 } 96 }