在微博模塊中,有一個API是可以發(fā)表帶一張圖片的微博的,當(dāng)然提交方式是POST。在封裝的時候,可能會遇到一個難點——如何上傳圖片?
要POST微博的同時帶有圖片,POST的內(nèi)容必須為Multipart form data格式的內(nèi)容,這個呢,我用到.NET 45中新增的一個相當(dāng)強大的HttpClient類,位于System.Net.Http命名空間下。這個類的好處在于,它把許多HTTP操作都封裝了,讓我們使用起來不至于過于痛苦。
源碼下載:http://vdisk.weibo.com/s/z7iFc2gCCwC1b
無論是GET請求還是POST請求,HttpClient類都允許我們發(fā)送一個HttpContent對象,它封裝了HTTP內(nèi)容數(shù)據(jù),當(dāng)然它是一個抽象類,我們用的是它的派生類,請看下圖:

StringContent類是把一個字符串發(fā)送到服務(wù)器,StreamContent類表示數(shù)據(jù)內(nèi)容以流的形式收發(fā),F(xiàn)ormUrlEncodedContent類封裝的數(shù)據(jù),說簡單一點就是模擬我們在web頁上form元素中填寫的內(nèi)容。
而既有文本又有圖片文件的微博,應(yīng)該使用MultipartFormDataContent來封裝,即包含多個段的數(shù)據(jù),正因其有多個 Content-Disposition段,我們需要弄一個字符串作為分隔符,在這里,就是把微博正文和圖片文件的數(shù)據(jù)分隔開來,這個字符串常見的形式如“---------------------------a6ecd24f3a2b3cc5”。
于是,我在SDK中專為POST這種多段數(shù)據(jù)的HTTP內(nèi)容寫了一個SendRequestWithMultipartFormDataAsync,都是async方法,可以異步等待,這是新特性,有些人不太了解它,其實當(dāng)你了解后,你會發(fā)現(xiàn)await異步等待其實很環(huán)保,也節(jié)省不少代碼。
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; }用于分隔內(nèi)容的字符串,我是通過把DateTime對象中的Ticks這個數(shù)值轉(zhuǎn)為十六進制字符串來實現(xiàn)的,也就是代碼中的b變量。
1、new一個MultipartFormDataContent對象。
2、微博正文是字符串,所以用StringContent來封裝,然后調(diào)用MultipartFormDataContent對象的Add方法加進去。
3、對于圖片,我們可以使用流StreamContent,但要注意一個很關(guān)鍵的要素,就是在Add到multipart form data 內(nèi)容中的時候,一定要指定文件名。即調(diào)用以下重載:
public void Add(HttpContent content, string name, string fileName);
也就是必須為filename參數(shù)給予一個文件名,相對路徑,絕對路徑都無所謂,或者干脆一個文件名(如abc.jpg)都行。就是不能缺了這個參數(shù),否則會上傳失敗。
將內(nèi)容添加完畢后,就可以直接調(diào)用PostAsync方法向服務(wù)器POST數(shù)據(jù)了,完成后返回HttPResponseMessage類型的實例,它封裝了服務(wù)器回應(yīng)的各種消息,可通過IsSuccessStatusCode屬性判斷服務(wù)器是否返回正確的代碼(OK,200)。Content屬性返回服務(wù)器回應(yīng)的消息正文。
這樣,上傳圖片的問題就解決了。
新聞熱點
疑難解答