DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

POSTでデータを送信する

ここではHTTPサーバーにPOST要求を送信し、返される結果を受信する方法を幾つか紹介します。データの送信方法として、ここでは"application/x-www-form-urlencoded"と"multipart/form-data"による方法を紹介します。

なおここで紹介しているコードでは、HttpUtility.UrlEncodeメソッドを使っていますので、System.Web.dllを参照に加える必要があります。(サーバー側が、クライアントが送信するデータのURLエンコードを必要としていないのであれば、このメソッドを使う必要はありません。)

"application/x-www-form-urlencoded"でデータを送信する

通常(特に文字列だけを送信する場合)は、"application/x-www-form-urlencoded"でデータを送信することになるでしょう。

HttpWebRequestとHttpWebResponseを使った方法

HttpWebRequestとHttpWebResponseクラスを使って、GET要求により、指定したURLのソースを表示する方法はこちらで紹介しました。POST要求をするには、さらに、WebRequestクラスのMethod、ContentType、ContentLengthプロパティの設定、POSTするデータのエンコードと送信などの処理が必要になります。

次の例は、「IT用語辞典 e-Words」から「インターネット」という言葉を調べ、その結果を取得し、表示するものです。

VB.NET
コードを隠すコードを選択
'文字コードを指定する
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()
C#
コードを隠すコードを選択
//文字コードを指定する
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を使った方法

WebClientクラスのUploadValuesメソッドを使用すると、簡単に"application/x-www-form-urlencoded"によるデータの送信ができます。ただし、送信されるデータは必ずUTF-8でURLエンコードされますので、送信先がUTF-8を解釈できない場合は、使えません。

VB.NET
コードを隠すコードを選択
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)
C#
コードを隠すコードを選択
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を追加する必要があります。

VB.NET
コードを隠すコードを選択
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)
C#
コードを隠すコードを選択
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を使ったコードを示します。

VB.NET
コードを隠すコードを選択
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)
C#
コードを隠すコードを選択
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"は、ファイルをアップロードするなど、主にバイナリデータを送信する目的で使用されます。"multipart/form-data"の定義については、RFC2388にあります。

HttpWebRequestとHttpWebResponseを使った方法

以下にHttpWebRequestとHttpWebResponseを使った方法を紹介します。ここでは、upfileフィールドのファイルを送信するとともに、commentフィールドの文字列も送信しています。

VB.NET
コードを隠すコードを選択
'送信するファイルのパス
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()
C#
コードを隠すコードを選択
//送信するファイルのパス
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を使った方法

WebClient.UploadFileメソッドを使って、"multipart/form-data"でファイルを送信することができます。ただしこの場合は一つのファイルしか送信できず、それ以外のフィールドは送信できません。さらに、送信するファイルのフィールド名(Content-Dispositionのname)は"file"に固定されています。また、ファイル名はUTF-8でエンコードされます。このような制限があるため、WebClient.UploadFileメソッドを使うには、POST先のWebアプリケーションがそれに対応している必要があり、すでにあるWebアプリケーションに使用することは難しいでしょう。

VB.NET
コードを隠すコードを選択
'送信するファイルのパス
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)
C#
コードを隠すコードを選択
//送信するファイルのパス
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メソッドを使った方法

.NET Framework 2.0以降のVB.NETでは、My.Computer.Network.UploadFileメソッドを使ってファイルのアップロードをすることができます。このメソッドは、アップロードの進行状況をダイアログで表示することができ、ユーザーが途中でキャンセルすることもできます。内部では、WebClient.UploadFile(ダイアログを表示させたときはWebClient.UploadFileAsync)メソッドによりアップロードしているようです。

次の例では、ファイル"C:\image.gif"を"http://localhost/upload.php"にアップロードしています。進行状況ダイアログを表示し、ユーザーがキャンセルしてもエラーをスローしないようにしています。タイムアウトは60秒です。ユーザー名とパスワードも指定していますが、必要なければ、空の文字列("")で構いません。

VB.NET
コードを隠すコードを選択
'ユーザーインターフェイスを表示してファイルをアップロードする
My.Computer.Network.UploadFile( _
    "C:\test.gif", "http://localhost/upload.php", _
    "username", "password", _
    True, 60000, FileIO.UICancelOption.DoNothing)
C#
コードを隠すコードを選択
//参照に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);
  • 履歴:
  • 2006/11/20 「multipart/form-dataでデータを送信する」を追加。また、WebClientによる方法を追加。
  • 2007/1/20 .NET Framework 2.0に関する記述を追加。
  • 2007/2/21 My.Computer.Network.UploadFileメソッドを使用する方法を追加。
  • 2008/9/9 「"multipart/form-data"でデータを送信する」の「HttpWebRequestとHttpWebResponseを使った方法」で、送信するデータの最後に"--"を追加。(コメントでご指摘いただきました。)

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • 「???を参照に追加します」の意味が分からないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。