標籤:style blog http color 使用 strong
在微博模組中,有一個API是可以發錶帶一張圖片的微博的,當然提交方式是POST。在封裝的時候,可能會遇到一個痛點——如何上傳圖片?
要POST微博的同時帶有圖片,POST的內容必須為MultiPart form data格式的內容,這個呢,我用到.NET 45中新增的一個相當強大的HttpClient類,位於System.Net.Http命名空間下。這個類的好處在於,它把許多HTTP操作都封裝了,讓我們使用起來不至於過於痛苦。
源碼下載:http://vdisk.weibo.com/s/z7iFc2gCCwC1b
無論是GET請求還是POST請求,HttpClient類都允許我們發送一個HttpContent對象,它封裝了HTTP內容資料,當然它是一個抽象類別,我們用的是它的衍生類別,請看:
StringContent類是把一個字串發送到伺服器,StreamContent類表示資料內容以流的形式收發,FormUrlEncodedContent類封裝的資料,說簡單一點就是類比我們在web頁上form元素中填寫的內容。
而既有文本又有圖片檔案的微博,應該使用MultipartFormDataContent來封裝,即包含多個段的資料,正因其有多個 Content-Disposition段,我們需要弄一個字串作為分隔字元,在這裡,就是把微博本文和圖片檔案的資料分隔開來,這個字串常見的形式如“---------------------------a6ecd24f3a2b3cc5”。
於是,我在SDK中專為POST這種多段資料的HTTP內容寫了一個SendRequestWithMultipartFormDataAsync,都是async方法,可以非同步等待,這是新特性,有些人不太瞭解它,其實當你瞭解後,你會發現await非同步等待其實很環保,也節省不少代碼。
internal static async Task<TResult> SendRequestWithMultipartFormDataAsync<TResult>(string relateUrl, IDictionary<string, object> parms, string filename) { Uri reqUri = new Uri(API_BASE_RUI); reqUri = new Uri(reqUri, relateUrl); TResult result = default(TResult); using (HttpClient client = new HttpClient()) { string b = "---------------------" + DateTime.Now.Ticks.ToString("x"); MultipartFormDataContent formData = new MultipartFormDataContent(b); foreach (var pair in parms) { string str = pair.Value as string; if (str != null) { StringContent stringContent = new StringContent(pair.Value as string); formData.Add(stringContent, pair.Key); } Stream stream = pair.Value as Stream; if (stream != null) { StreamContent streamContent = new StreamContent(stream); formData.Add(streamContent, pair.Key, filename); } } var response = await client.PostAsync(reqUri, formData); if (response.IsSuccessStatusCode) { using (Stream backstream = await response.Content.ReadAsStreamAsync()) { result = JsonSerializeHelper.ReadDataFromJson<TResult>(backstream); } } else { ErrorData err = null; using (Stream errstream = await response.Content.ReadAsStreamAsync()) { err = JsonSerializeHelper.ReadDataFromJson<ErrorData>(errstream); } throw new WeiboException(err); } } return result; }
用於分隔內容的字串,我是通過把DateTime對象中的Ticks這個數值轉為十六進位字串來實現的,也就是代碼中的b變數。
1、new一個MultipartFormDataContent對象。
2、微博本文是字串,所以用StringContent來封裝,然後調用MultipartFormDataContent對象的Add方法加進去。
3、對於圖片,我們可以使用流StreamContent,但要注意一個很關鍵的要素,就是在Add到multipart form data 內容中的時候,一定要指定檔案名稱。即調用以下重載:
public void Add(HttpContent content, string name, string fileName);
也就是必須為filename參數給予一個檔案名稱,相對路徑,絕對路徑都無所謂,或者乾脆一個檔案名稱(如abc.jpg)都行。就是不能缺了這個參數,否則會上傳失敗。
將內容添加完畢後,就可以直接調用PostAsync方法向伺服器POST資料了,完成後返回HttpResponseMessage類型的執行個體,它封裝了伺服器回應的各種訊息,可通過IsSuccessStatusCode屬性判斷伺服器是否返回正確的代碼(OK,200)。Content屬性返回伺服器回應的訊息本文。
這樣,上傳圖片的問題就解決了。