我們已經談完了,如何使用 HttpClient 進行 Web API 的 CRUD 操作,以及不同的資料編碼方式,讓我們可以順利的把不同格式資料,傳遞到遠端 Web API 控制器的動作方法內。
現在,我們需要進行二進位檔案型態的操作,在這兩篇文章中,我們會使用圖片檔案作為練習範例,我們需要從網站上下載圖片檔案、另外需要從用戶端把圖片檔案上傳到後端伺服器中;首先,我們來看看如何從網站下載圖片檔案(同樣的作法,你可以下載聲音、影片、PDF、Word等不同類型檔案)。
了解更多關於 [HttpClient Class] 的使用方式
了解更多關於 [使用 async 和 await 進行非同步程式設計] 的使用方式
下載圖片檔案到本機儲存空間內
我們在這裡撰寫一個方法
DownloadImageAsync
,並且接收一個參數,指出要下載的圖片檔案名稱,接者,會與字串 http://vulcanwebapi.azurewebsites.net/Datas/
組合成為一個新的 URL,這個 URL 將會指向網站伺服器上的一個圖片;最後,我們只需要對這個 URL 發出 GetAsync
方法的引數,這樣, HttpClient 類別物件就會取得這個遠端伺服器上的圖片檔案。
當取得了
HttpResponseMessage
類別物件之後,先檢查此次的 Http 呼叫是否為成功狀態,接者,使用 File.Open
建立一個檔案並且取得該檔案的 FileStream
物件,我們需要透過此物件,來將資料寫入到本機檔案中。
想要取得遠端伺服器上
HttpResponseMessage
類別物件的 Stream,可以使用這個 await response.Content.ReadAsStreamAsync()
表示式,最後,使用 stream.CopyTo(filestream);
敘述,把遠端伺服器上的內容,透過 Stream 寫入到本機檔案 Stream,完成產生本機的檔案。private static async Task<APIResult> DownloadImageAsync(string filename)
{
string ImgFilePath = $"My_{filename}";
ImgFilePath = Path.Combine(Environment.CurrentDirectory, ImgFilePath);
APIResult fooAPIResult;
using (HttpClientHandler handler = new HttpClientHandler())
{
using (HttpClient client = new HttpClient(handler))
{
try
{
#region 呼叫遠端 Web API
//string FooUrl = $"http://localhost:53494/api/Upload";
string FooUrl = $"http://vulcanwebapi.azurewebsites.net/Datas/";
HttpResponseMessage response = null;
#region 設定相關網址內容
var fooFullUrl = $"{FooUrl}{filename}";
response = await client.GetAsync(fooFullUrl);
#endregion
#endregion
#region 處理呼叫完成 Web API 之後的回報結果
if (response != null)
{
if (response.IsSuccessStatusCode == true)
{
using (var filestream = File.Open(ImgFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var stream = await response.Content.ReadAsStreamAsync())
{
stream.CopyTo(filestream);
}
}
fooAPIResult = new APIResult
{
Success = true,
Message = string.Format("Error Code:{0}, Error Message:{1}", response.StatusCode, response.Content),
Payload = ImgFilePath,
};
}
else
{
fooAPIResult = new APIResult
{
Success = false,
Message = string.Format("Error Code:{0}, Error Message:{1}", response.StatusCode, response.RequestMessage),
Payload = null,
};
}
}
else
{
fooAPIResult = new APIResult
{
Success = false,
Message = "應用程式呼叫 API 發生異常",
Payload = null,
};
}
#endregion
}
catch (Exception ex)
{
fooAPIResult = new APIResult
{
Success = false,
Message = ex.Message,
Payload = ex,
};
}
}
}
return fooAPIResult;
}
觸發的 Web API 動作
這個範例中,將會指向 URL
http://vulcanwebapi.azurewebsites.net/Datas/vulcan.png
,此時,將會要求網站伺服器回傳該檔案內容到用戶端(當然,您在後端 Web API 主機,也可以設計出各種 GET / POST / PUT 動作方法,回傳這個圖片內容到用戶端),其該動作的原始碼如下所示。進行測試
在程式進入點函式,我們直接呼叫 DownloadImageAsync 方法,並且在應用程式可執行組件所在目錄,開啟這個圖片檔案。
static async Task Main(string[] args)
{
var fooResult = await DownloadImageAsync("vulcan.png");
Process myProcess = new Process();
try
{
// true is the default, but it is important not to set it to false
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.FileName = fooResult.Payload.ToString();
myProcess.Start();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine($"Press any key to Exist...{Environment.NewLine}");
Console.ReadKey();
}
執行結果
這個測試將會輸出底下內容
Press any key to Exist...
HTTP 傳送與接收原始封包
讓我們來看看,這個 Web API 的呼叫動作中,在請求 (Request) 與 反應 (Response) 這兩個階段,會在網路上傳送了那些 HTTP 資料
- 請求 (Request)在這裡是提供一個簡單的 GET 要求呼叫。
GET http://vulcanwebapi.azurewebsites.net/Datas/vulcan.png HTTP/1.1
Host: vulcanwebapi.azurewebsites.net
Connection: Keep-Alive
- 反應 (Response)在 Http 回應封包中,我們看到了總共圖片檔案的長度為 160387,這部分可以從 Http Header 的
Content-Length
看到,另外,從 Http HeaderContent-Type: image/png
可以看得出來,伺服器回報這個回應內容是個 .png 圖片檔案。在最後面是這個圖片檔案的內容,由於這些都是經過編碼後的內容,我們僅僅顯示一小部分作為示意之用。
HTTP/1.1 200 OK
Content-Length: 160387
Content-Type: image/png
Last-Modified: Sun, 08 Oct 2017 16:09:22 GMT
Accept-Ranges: bytes
ETag: "1d3404fcd99d783"
Server: Kestrel
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=9d3635139ab6649f453417d1e9047b7ed7a79b7bef031b04afeb6a2c58b33d4e;Path=/;HttpOnly;Domain=vulcanwebapi.azurewebsites.net
Date: Mon, 23 Oct 2017 02:10:58 GMT
PNG
IHDR u pHYs + tIME 8ǫe tEXtAuthor H tEXtDescription !#
tEXtCopyr
*** FIDDLER: RawDisplay truncated at 128 characters. Right-click to disable truncation. ***
相關文章索引
C# HttpClient WebAPI 系列文章索引
了解更多關於 [HttpClient Class] 的使用方式
了解更多關於 [使用 async 和 await 進行非同步程式設計] 的使用方式
關於 Xamarin 在台灣的學習技術資源
歡迎加入 Xamarin 實驗室 粉絲團,在這裡,將會經常性的貼出各種關於 Xamarin / Visual Studio / .NET 的相關消息、文章、技術開發等文件,讓您可以隨時掌握第一手的 Xamarin 方面消息。
歡迎加入 Xamarin.Forms @ Taiwan,這是台灣的 Xamarin User Group,若您有任何關於 Xamarin / Visual Studio / .NET 上的問題,都可以在這裡來與各方高手來進行討論、交流。
Xamarin 實驗室 部落格 是作者本身的部落格,這個部落格將會專注於 Xamarin 之跨平台 (Android / iOS / UWP) 方面的各類開技術探討、研究與分享的文章,最重要的是,它是全繁體中文。
Xamarin.Forms 系列課程 想要快速進入到 Xamarin.Forms 的開發領域,學會各種 Xamarin.Forms 跨平台開發技術,例如:MVVM、Prism、Data Binding、各種 頁面 Page / 版面配置 Layout / 控制項 Control 的用法等等,千萬不要錯過這些 Xamarin.Forms 課程