ここではHTTPサーバーにPOST要求を送信し、返される結果を受信する方法を幾つか紹介します。データの送信方法として、ここでは"application/x-www-form-urlencoded"と"multipart/form-data"による方法を紹介します。
なおここで紹介しているコードでは、HttpUtility.UrlEncodeメソッドを使っていますので、System.Web.dllを参照に加える必要があります。(サーバー側が、クライアントが送信するデータのURLエンコードを必要としていないのであれば、このメソッドを使う必要はありません。)
通常(特に文字列だけを送信する場合)は、"application/x-www-form-urlencoded"でデータを送信することになるでしょう。
HttpWebRequestとHttpWebResponseクラスを使って、GET要求により、指定したURLのソースを表示する方法はこちらで紹介しました。POST要求をするには、さらに、WebRequestクラスのMethod、ContentType、ContentLengthプロパティの設定、POSTするデータのエンコードと送信などの処理が必要になります。
次の例は、「IT用語辞典 e-Words」から「インターネット」という言葉を調べ、その結果を取得し、表示するものです。
'文字コードを指定する Dim enc As System.Text.Encoding = _ System.Text.Encoding.GetEncoding("shift_jis") 'POST送信する文字列を作成 Dim postData As String = _ "inlang=ja&word=" + _ System.Web.HttpUtility.UrlEncode("インターネット", enc) 'バイト型配列に変換 Dim postDataBytes As Byte() = _ System.Text.Encoding.ASCII.GetBytes(postData) 'WebRequestの作成 Dim req As System.Net.WebRequest = _ System.Net.WebRequest.Create("http://www.e-words.ne.jp/search.asp") 'メソッドにPOSTを指定 req.Method = "POST" 'ContentTypeを"application/x-www-form-urlencoded"にする req.ContentType = "application/x-www-form-urlencoded" 'POST送信するデータの長さを指定 req.ContentLength = postDataBytes.Length 'データをPOST送信するためのStreamを取得 Dim reqStream As System.IO.Stream = req.GetRequestStream() '送信するデータを書き込む reqStream.Write(postDataBytes, 0, postDataBytes.Length) reqStream.Close() 'サーバーからの応答を受信するためのWebResponseを取得 Dim res As System.Net.WebResponse = req.GetResponse() '応答データを受信するためのStreamを取得 Dim resStream As System.IO.Stream = res.GetResponseStream() '受信して表示 Dim sr As New System.IO.StreamReader(resStream, enc) Console.WriteLine(sr.ReadToEnd()) '閉じる sr.Close()
//文字コードを指定する System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis"); //POST送信する文字列を作成 string postData = "inlang=ja&word=" + System.Web.HttpUtility.UrlEncode("インターネット", enc); //バイト型配列に変換 byte[] postDataBytes = System.Text.Encoding.ASCII.GetBytes(postData); //WebRequestの作成 System.Net.WebRequest req = System.Net.WebRequest.Create("http://www.e-words.ne.jp/search.asp"); //メソッドにPOSTを指定 req.Method = "POST"; //ContentTypeを"application/x-www-form-urlencoded"にする req.ContentType = "application/x-www-form-urlencoded"; //POST送信するデータの長さを指定 req.ContentLength = postDataBytes.Length; //データをPOST送信するためのStreamを取得 System.IO.Stream reqStream = req.GetRequestStream(); //送信するデータを書き込む reqStream.Write(postDataBytes, 0, postDataBytes.Length); reqStream.Close(); //サーバーからの応答を受信するためのWebResponseを取得 System.Net.WebResponse res = req.GetResponse(); //応答データを受信するためのStreamを取得 System.IO.Stream resStream = res.GetResponseStream(); //受信して表示 System.IO.StreamReader sr = new System.IO.StreamReader(resStream, enc); Console.WriteLine(sr.ReadToEnd()); //閉じる sr.Close();
この例ではPOSTするデータが日本語のため、その部分をURLエンコードしています。URLエンコードするためにHttpUtility.UrlEncodeメソッドを使用していますが、そのためにSystem.Web.dllを参照する必要があり、さらに残念なことに、このHttpUtility.UrlEncodeメソッドはWindows2000以上でしか使用できません。
ここではShift JISでエンコード、デコードしていますが、適当な文字コードのEncodingを使用する必要があります。Encodingについては、こちらをご覧ください。
WebClientクラスのUploadValuesメソッドを使用すると、簡単に"application/x-www-form-urlencoded"によるデータの送信ができます。ただし、送信されるデータは必ずUTF-8でURLエンコードされますので、送信先がUTF-8を解釈できない場合は、使えません。
Dim url As String = "http://localhost/test.aspx" Dim wc As New System.Net.WebClient 'NameValueCollectionの作成 Dim ps As New System.Collections.Specialized.NameValueCollection '送信するデータ(フィールド名と値の組み合わせ)を追加 ps.Add("word", "インターネット") ps.Add("id", "1") 'データを送信し、また受信する Dim resData As Byte() = wc.UploadValues(url, ps) wc.Dispose() '受信したデータを表示する Dim resText As String = System.Text.Encoding.UTF8.GetString(resData) Console.WriteLine(resText)
string url = "http://localhost/test.aspx"; System.Net.WebClient wc = new System.Net.WebClient(); //NameValueCollectionの作成 System.Collections.Specialized.NameValueCollection ps = new System.Collections.Specialized.NameValueCollection(); //送信するデータ(フィールド名と値の組み合わせ)を追加 ps.Add("word", "インターネット"); ps.Add("id", "1"); //データを送信し、また受信する byte[] resData = wc.UploadValues(url, ps); wc.Dispose(); //受信したデータを表示する string resText = System.Text.Encoding.UTF8.GetString(resData); Console.WriteLine(resText);
UTF-8以外の文字コードでデータを送信する必要があるならば、WebClient.UploadDataメソッドを使う方法があります。この場合は、HeadersプロパティにContent-Typeを追加する必要があります。
Dim url As String = "http://www.e-words.ne.jp/search.asp" '文字コードを指定する Dim enc As System.Text.Encoding = _ System.Text.Encoding.GetEncoding("shift_jis") 'POST送信する文字列を作成 Dim postData As String = _ "id=1&word=" + _ System.Web.HttpUtility.UrlEncode("インターネット", enc) 'バイト型配列に変換 Dim postDataBytes As Byte() = enc.GetBytes(postData) Dim wc As New System.Net.WebClient 'ヘッダにContent-Typeを加える wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded") 'データを送信し、また受信する Dim resData As Byte() = wc.UploadData(url, postDataBytes) wc.Dispose() '受信したデータを表示する Dim resText As String = enc.GetString(resData) Console.WriteLine(resText)
string url = "http://www.e-words.ne.jp/search.asp"; //文字コードを指定する System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis"); //POST送信する文字列を作成 string postData = "id=1&word=" + System.Web.HttpUtility.UrlEncode("インターネット", enc); //バイト型配列に変換 byte[] postDataBytes = enc.GetBytes(postData); System.Net.WebClient wc = new System.Net.WebClient(); //ヘッダにContent-Typeを加える wc.Headers.Add("Content-Type","application/x-www-form-urlencoded"); //データを送信し、また受信する byte[] resData = wc.UploadData(url, postDataBytes); wc.Dispose(); //受信したデータを表示する string resText = enc.GetString(resData); Console.WriteLine(resText);
.NET Framework 2.0以降であれば、UploadStringメソッドを使って、上のUploadDataを使ったコードをほんの少しだけ簡単にできます。以下にUploadStringを使ったコードを示します。
Dim url As String = "http://www.e-words.ne.jp/search.asp" '文字コードを指定する Dim enc As System.Text.Encoding = _ System.Text.Encoding.GetEncoding("shift_jis") 'POST送信する文字列を作成 Dim postData As String = "id=1&word=" + _ System.Web.HttpUtility.UrlEncode("インターネット", enc) Dim wc As New System.Net.WebClient() '文字コードを指定する wc.Encoding = enc 'ヘッダにContent-Typeを加える wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded") 'データを送信し、また受信する Dim resText As String = wc.UploadString(url, postData) wc.Dispose() '受信したデータを表示する Console.WriteLine(resText)
string url = "http://www.e-words.ne.jp/search.asp"; //文字コードを指定する System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis"); //POST送信する文字列を作成 string postData = "id=1&word=" + System.Web.HttpUtility.UrlEncode("インターネット", enc); System.Net.WebClient wc = new System.Net.WebClient(); //文字コードを指定する wc.Encoding = enc; //ヘッダにContent-Typeを加える wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); //データを送信し、また受信する string resText = wc.UploadString(url, postData); wc.Dispose(); //受信したデータを表示する Console.WriteLine(resText);
"multipart/form-data"は、ファイルをアップロードするなど、主にバイナリデータを送信する目的で使用されます。"multipart/form-data"の定義については、RFC2388にあります。
以下にHttpWebRequestとHttpWebResponseを使った方法を紹介します。ここでは、upfileフィールドのファイルを送信するとともに、commentフィールドの文字列も送信しています。
'送信するファイルのパス Dim filePath As String = "C:\test.gif" Dim fileName As String = System.IO.Path.GetFileName(filePath) '送信先のURL Dim url As String = "http://localhost/upload.php" '文字コード Dim enc As System.Text.Encoding = _ System.Text.Encoding.GetEncoding("shift_jis") '区切り文字列 Dim boundary As String = System.Environment.TickCount.ToString() 'WebRequestの作成 Dim req As System.Net.HttpWebRequest = _ CType(System.Net.WebRequest.Create(url), _ System.Net.HttpWebRequest) 'メソッドにPOSTを指定 req.Method = "POST" 'ContentTypeを設定 req.ContentType = "multipart/form-data; boundary=" + boundary 'POST送信するデータを作成 Dim postData As String = "" postData = "--" + boundary + vbCrLf + _ "Content-Disposition: form-data; name=""comment""" + _ vbCrLf + vbCrLf + "これは、テストです。" + vbCrLf + _ "--" + boundary + vbCrLf + _ "Content-Disposition: form-data; name=""upfile""; filename=""" + _ fileName + """" + vbCrLf + _ "Content-Type: application/octet-stream" + vbCrLf + _ "Content-Transfer-Encoding: binary" + vbCrLf + vbCrLf 'バイト型配列に変換 Dim startData As Byte() = enc.GetBytes(postData) postData = vbCrLf + "--" + boundary + "--" + vbCrLf Dim endData As Byte() = enc.GetBytes(postData) '送信するファイルを開く Dim fs As New System.IO.FileStream( _ filePath, _ System.IO.FileMode.Open, _ System.IO.FileAccess.Read) 'POST送信するデータの長さを指定 req.ContentLength = startData.Length + endData.Length + fs.Length 'データをPOST送信するためのStreamを取得 Dim reqStream As System.IO.Stream = req.GetRequestStream() '送信するデータを書き込む reqStream.Write(startData, 0, startData.Length) 'ファイルの内容を送信 Dim readData(&H1000) As Byte Dim readSize As Integer = 0 While True readSize = fs.Read(readData, 0, readData.Length) If readSize = 0 Then Exit While End If reqStream.Write(readData, 0, readSize) End While fs.Close() reqStream.Write(endData, 0, endData.Length) reqStream.Close() 'サーバーからの応答を受信するためのWebResponseを取得 Dim res As System.Net.HttpWebResponse = _ CType(req.GetResponse(), System.Net.HttpWebResponse) '応答データを受信するためのStreamを取得 Dim resStream As System.IO.Stream = res.GetResponseStream() '受信して表示 Dim sr As New System.IO.StreamReader(resStream, enc) Console.WriteLine(sr.ReadToEnd()) '閉じる sr.Close()
//送信するファイルのパス string filePath = "C:\\test.gif"; string fileName = System.IO.Path.GetFileName(filePath); //送信先のURL string url = "http://localhost/upload.php"; //文字コード System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis"); //区切り文字列 string boundary = System.Environment.TickCount.ToString(); //WebRequestの作成 System.Net.HttpWebRequest req = (System.Net.HttpWebRequest) System.Net.WebRequest.Create(url); //メソッドにPOSTを指定 req.Method = "POST"; //ContentTypeを設定 req.ContentType = "multipart/form-data; boundary=" + boundary; //POST送信するデータを作成 string postData = ""; postData = "--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"comment\"\r\n\r\n" + "これは、テストです。\r\n" + "--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"upfile\"; filename=\"" + fileName + "\"\r\n" + "Content-Type: application/octet-stream\r\n" + "Content-Transfer-Encoding: binary\r\n\r\n"; //バイト型配列に変換 byte[] startData = enc.GetBytes(postData); postData = "\r\n--" + boundary + "--\r\n"; byte[] endData = enc.GetBytes(postData); //送信するファイルを開く System.IO.FileStream fs = new System.IO.FileStream( filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read); //POST送信するデータの長さを指定 req.ContentLength = startData.Length + endData.Length + fs.Length; //データをPOST送信するためのStreamを取得 System.IO.Stream reqStream = req.GetRequestStream(); //送信するデータを書き込む reqStream.Write(startData, 0, startData.Length); //ファイルの内容を送信 byte[] readData = new byte[0x1000]; int readSize = 0; while (true) { readSize = fs.Read(readData, 0, readData.Length); if (readSize == 0) break; reqStream.Write(readData, 0, readSize); } fs.Close(); reqStream.Write(endData, 0, endData.Length); reqStream.Close(); //サーバーからの応答を受信するためのWebResponseを取得 System.Net.HttpWebResponse res = (System.Net.HttpWebResponse) req.GetResponse(); //応答データを受信するためのStreamを取得 System.IO.Stream resStream = res.GetResponseStream(); //受信して表示 System.IO.StreamReader sr = new System.IO.StreamReader(resStream, enc); Console.WriteLine(sr.ReadToEnd()); //閉じる sr.Close();
WebClient.UploadFileメソッドを使って、"multipart/form-data"でファイルを送信することができます。ただしこの場合は一つのファイルしか送信できず、それ以外のフィールドは送信できません。さらに、送信するファイルのフィールド名(Content-Dispositionのname)は"file"に固定されています。また、ファイル名はUTF-8でエンコードされます。このような制限があるため、WebClient.UploadFileメソッドを使うには、POST先のWebアプリケーションがそれに対応している必要があり、すでにあるWebアプリケーションに使用することは難しいでしょう。
'送信するファイルのパス Dim filePath As String = "C:\test.gif" '送信先のURL Dim url As String = "http://localhost/upload.php" Dim wc As New System.Net.WebClient 'データを送信し、また受信する Dim resData As Byte() = wc.UploadFile(url, filePath) '受信したデータを表示する Dim resText As String = System.Text.Encoding.UTF8.GetString(resData) Console.WriteLine(resText)
//送信するファイルのパス string filePath = "C:\\test.gif"; //送信先のURL string url = "http://localhost/upload.php"; System.Net.WebClient wc = new System.Net.WebClient(); //データを送信し、また受信する byte[] resData = wc.UploadFile(url, filePath); //受信したデータを表示する string resText = System.Text.Encoding.UTF8.GetString(resData); Console.WriteLine(resText);
また、WebClient.UploadValuesメソッドを使っても可能でしょう。ただ、UploadValuesではバイト型配列を一度に送信するため、大きいファイルを送信するのは厳しいでしょう。
.NET Framework 2.0からは、非同期にファイルのアップロードを行うUploadFileAsyncメソッドが追加されました。大きなファイルをアップロードする際に使用するとよいでしょう。
.NET Framework 2.0以降のVB.NETでは、My.Computer.Network.UploadFileメソッドを使ってファイルのアップロードをすることができます。このメソッドは、アップロードの進行状況をダイアログで表示することができ、ユーザーが途中でキャンセルすることもできます。内部では、WebClient.UploadFile(ダイアログを表示させたときはWebClient.UploadFileAsync)メソッドによりアップロードしているようです。
次の例では、ファイル"C:\image.gif"を"http://localhost/upload.php"にアップロードしています。進行状況ダイアログを表示し、ユーザーがキャンセルしてもエラーをスローしないようにしています。タイムアウトは60秒です。ユーザー名とパスワードも指定していますが、必要なければ、空の文字列("")で構いません。
'ユーザーインターフェイスを表示してファイルをアップロードする My.Computer.Network.UploadFile( _ "C:\test.gif", "http://localhost/upload.php", _ "username", "password", _ True, 60000, FileIO.UICancelOption.DoNothing)
//参照にMicrosoft.VisualBasic.dllを追加する必要がある //ユーザーインターフェイスを表示してファイルをアップロードする Microsoft.VisualBasic.Devices.Network network = new Microsoft.VisualBasic.Devices.Network(); network.UploadFile( "C:\\test.gif", "http://localhost/upload.php", "username", "password", true, 60000, Microsoft.VisualBasic.FileIO.UICancelOption.DoNothing);