WebRequest/WebResponseクラスでPOSTメソッドによりデータを送信するには?.NET TIPS

» 2005年07月01日 05時00分 公開
[遠藤孝信デジタルアドバンテージ]
.NET TIPS
Insider.NET


「.NET TIPS」のインデックス

連載目次

 「TIPS:WebRequest/WebResponseクラスでWebページを取得するには?」では、GETメソッドによるWebページの取得について解説しているが、本稿では、POSTメソッドによりWebページにデータを送信してアクセスする方法について解説する。

POSTメソッドによるアクセスの手順

 WebRequestクラス/WebResponseクラス(ともにSystem.Net名前空間)を使用してGETメソッドによりWebページにアクセスするには、上記のTIPSで示しているように、基本的には次のような処理の流れになる。

1. WebRequestクラスによりリクエスト(HttpWebRequestオブジェクト)を作成

2. GetResponseメソッドによりレスポンス(WebResponseオブジェクト)を取得

3. GetResponseStreamメソッドにより得たストリームから結果を取得

 POSTメソッドによりデータ(以降、ポスト・データ)を送信する場合には、リクエストであるHttpWebRequestオブジェクトに対して、以下のような設定が上記1.2.の間に必要となる。

1.1. Methodプロパティを「POST」に設定(デフォルトは「GET」)

1.2. ContentTypeプロパティを「application/x-www-form-urlencoded」に設定して、ポスト・データのコンテンツ・タイプを指定

1.3. ContentLengthプロパティに送信するポスト・データの長さを設定

1.4. GetRequestStreamメソッドにより得たストリームに対してポスト・データを書き込む

 以下に実際のWebページの例を取り上げながら、これらの詳細を解説していく。

Google翻訳機能で送信されるデータ

 ここでは、Googleが提供している翻訳機能(現時点ではBETA版)にアクセスするプログラムを作成してみる。Google翻訳機能では、以下のようなページにより、さまざまな言語間での機械翻訳を実行することができる。

Googleが提供している翻訳機能(BETA) Googleが提供している翻訳機能(BETA)
この画面では、日本語の文章を英語に機械翻訳している。[Translate text]に翻訳したい日本語を入力し、[from]で「Japanese to English BETA」を選択し、[Translate]ボタンをクリックして翻訳を実行する。

 Google翻訳機能ページのソース(HTMLデータ)を見ると、翻訳したい文章を入力する部分のフォームは次のようになっている。

<form action=translate_t method=post>

  <textarea name=text rows=5 cols=45 wrap=PHYSICAL>
  </textarea>

  <select name=langpair>
    ……略……
    <option value="ja|en">Japanese to English BETA
    </option>
    ……略……
  </select>

  <input type=hidden name=hl value="en">
  <input type=hidden name=ie value="UTF8">
  <input type=submit value="Translate">
</form>

Google翻訳機能ページのHTML(抜粋)
<textarea>タグがテキストボックス、<select>タグがコンボボックス、最後の<input type=submit value="Translate">タグが[Translate]ボタンを記述している。

 このフォームでは、以下の表に示した4つのデータを、「http://translate.google.com/translate_t」に対してポスト(送信)していることになる。

パラメータ名 内容
text 翻訳したい文字列 UTF-8でエンコードが必要
langpair ja|en 日本語から英語へ翻訳する場合の値
hl en 結果ページで使用される言語
ie UTF8 入力文字列の文字コード
Google翻訳機能ページでポストされる4つのデータ
これらの各データの内容は筆者が独自に調査したものであり、将来的に変更される可能性がある。

 プログラムからGoogle翻訳機能を利用する場合には、これらのデータをポスト・データとして作成し、上記のURLにアクセスすればよい。

ポスト・データの作成と書き込み

 フォームで入力されたデータがWebページに送信される場合、そのデータの形式(コンテンツ・タイプ)にはいくつかの種類があるが、デフォルト(<form>タグのenctype属性で特に指定されていない場合)の形式が「application/x-www-form-urlencoded」という形式である(詳細については「HTML 4.01 Specification」の「17.13.4 Form content types」などを参照)。

 これは、「パラメータ名と値」を=記号でペアにし、各ペアを&記号で連結する形式だ(日本語や一部の記号についてはエンコードが必要となる。このエンコードについては「TIPS:文字列をURLエンコードするには?」を参照)。

 つまりGoogle翻訳機能の場合には、以下のようなポスト・データが送信されることになる。

text=<エンコードした文字列>&langpair=ja|en&hl=en&ie=UTF8



 プログラムからアクセスする場合には、このような文字列を作成して送信すればよい。具体的には、この文字列をバイト列に変換してから、リクエストであるHttpWebRequestオブジェクトのGetRequestStreamメソッドにより得たストリームに対して書き込む。

 上記のような文字列が文字列変数paramに入っているとすると、このためのコードは次のようになる(C#の場合。VB.NETの場合は以下のサンプル・プログラムを参照)。

byte[] data = Encoding.ASCII.GetBytes(param);

Stream reqStream = req.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();


 文字列のバイト列への変換については「TIPS:文字列をシフトJISとしてバイト列に変換するには?」で解説している。

Google翻訳機能により翻訳を行うサンプル・プログラム

 以下に、Google翻訳機能を使って日本語の文字列を英語に翻訳するサンプル・プログラムを示す。

 なお、このプログラムではポスト・データとなる文字列の作成を分かりやすく記述するためにハッシュテーブルを利用している。これについては「TIPS:ハッシュテーブル(連想配列)を使うには?」で解説している。

// jetrans.cs

using System;
using System.IO;
using System.Net;
using System.Web;
using System.Text;
using System.Collections;

public class GoogleTranslate {
  static void Main() {

    Encoding enc = Encoding.UTF8;

    string input = "私は普通のC#プログラマです。";

    string url = "http://translate.google.com/translate_t";
    string param = "";

    // ポスト・データの作成
    Hashtable ht = new Hashtable();

    ht["text"] = HttpUtility.UrlEncode(input, enc);
    ht["langpair"] = "ja|en";
    ht["hl"] = "en";
    ht["ie"] = "UTF8";

    foreach (string k in ht.Keys) {
      param += String.Format("{0}={1}&", k, ht[k]);
    }
    byte[] data = Encoding.ASCII.GetBytes(param);

    // リクエストの作成
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
    req.Method = "POST";
    req.ContentType = "application/x-www-form-urlencoded";
    req.ContentLength = data.Length;

    // ポスト・データの書き込み
    Stream reqStream = req.GetRequestStream();
    reqStream.Write(data, 0, data.Length);
    reqStream.Close();

    // レスポンスの取得と読み込み
    WebResponse res = req.GetResponse();
    Stream resStream = res.GetResponseStream();
    StreamReader sr = new StreamReader(resStream, enc);
    string html = sr.ReadToEnd();
    sr.Close();
    resStream.Close();

    // 必要なデータの切り出し
    // 結果は「wrap=PHYSICAL>〜</textarea>」にあるという前提
    string startmark = "wrap=PHYSICAL>";
    int start = html.IndexOf(startmark) + startmark.Length;
    int end = html.IndexOf("</textarea>", start);
    string result = html.Substring(start, end - start);

    Console.WriteLine(result);
    // 出力:I am the normal C# programmer.
  }
}

// コンパイル方法:jetrans.cs

Google翻訳機能により日英翻訳を行うC#のサンプル・プログラム(jetrans.cs)
jetrans.csのダウンロード

' jetrans.vb

Imports System
Imports System.IO
Imports System.Net
Imports System.Web
Imports System.Text
Imports System.Collections

Public Class GoogleTranslate
  Shared Sub Main()
    Dim enc As Encoding = Encoding.UTF8

    Dim input As String = "私は普通のC#プログラマです。"

    Dim url As String = "http://translate.google.com/translate_t"
    Dim param As String = ""

    ' ポスト・データの作成
    Dim ht As Hashtable = new Hashtable()

    ht("text") = HttpUtility.UrlEncode(input, enc)
    ht("langpair") = "ja|en"
    ht("hl") = "en"
    ht("ie") = "UTF8"

    For Each k As String In ht.Keys
      param = param & String.Format("{0}={1}&", k, ht(k))
    Next
    Dim data As byte() = Encoding.ASCII.GetBytes(param)

    ' リクエストの作成
    Dim req As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
    req.Method = "POST"
    req.ContentType = "application/x-www-form-urlencoded"
    req.ContentLength = data.Length

    ' ポスト・データの書き込み
    Dim reqStream As Stream = req.GetRequestStream()
    reqStream.Write(data, 0, data.Length)
    reqStream.Close()

    ' レスポンスの取得と読み込み
    Dim res As WebResponse = req.GetResponse()
    Dim resStream As Stream = res.GetResponseStream()
    Dim sr As StreamReader = new StreamReader(resStream, enc)
    Dim html As String = sr.ReadToEnd()
    sr.Close()
    resStream.Close()

    ' 必要なデータの切り出し
    ' 結果は「wrap=PHYSICAL>〜</textarea>」にあるという前提
    Dim startmark As String = "wrap=PHYSICAL>"
    Dim rstart As Integer = html.IndexOf(startmark) + startmark.Length
    Dim rend As Integer = html.IndexOf("</textarea>", rstart)
    Dim result As String = html.Substring(rstart, rend - rstart)

    Console.WriteLine(result)
    ' 出力:I am the normal C# programmer.
  End Sub
End Class

' コンパイル方法:vbc /r:System.dll /r:System.Web.dll jetrans.vb

Google翻訳機能により日英翻訳を行うVB.NETのサンプル・プログラム(jetrans.vb)
jetrans.vbのダウンロード

 結果ページ(レスポンス)の取得についてはGETメソッドを使う場合と同様であるため、詳しくは「TIPS:WebRequest/WebResponseクラスでWebページを取得するには?」を参照していただきたい。

カテゴリ:クラス・ライブラリ 処理対象:ネットワーク
使用ライブラリ:WebRequestクラス(System.Net名前空間)
使用ライブラリ:WebResponseクラス(System.Net名前空間)
使用ライブラリ:HttpWebRequestクラス(System.Net名前空間)
使用ライブラリ:HttpUtilityクラス(System.Web名前空間)
使用ライブラリ:Hashtableクラス(System.Collections名前空間)
関連TIPS:WebRequest/WebResponseクラスでWebページを取得するには?
関連TIPS:文字列をURLエンコードするには?
関連TIPS:文字列をシフトJISとしてバイト列に変換するには?
関連TIPS:ハッシュテーブル(連想配列)を使うには?


「.NET TIPS」のインデックス

.NET TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。