tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re^2: .netでのストリームの扱い
投稿日: 2015/09/01(Tue) 12:14
投稿者魔界の仮面弁士
> > これをvb.net標準のコードにするのはどうすればよいのでしょうか
> HttpWebRequest の GetRequestStream() で得られるストリームに
> 書きこめば良いかと思います。

HttpWebRequest を使って、google 画像検索に画像ファイルをマルチパートで POST してみました。
参考になれば。


Imports System.Net
Imports System.IO
Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim pngImageFile As String = "C:\TEMP\img.png"

        'これは google image search API の URL ではなく、
        'ブラウザで「google 画像検索」を呼び出したときの
        'アップロード用の URL です
        Dim url As String = "https://www.google.co.jp/searchbyimage/upload"

        '任意のバウンダリ文字列を用意
        Dim boundary As String = StrDup(5, "-") & Guid.NewGuid().ToString("N")


        'multipart/form-data 形式で POST するための準備
        Dim req = DirectCast(WebRequest.Create(url), HttpWebRequest)
        req.Method = WebRequestMethods.Http.Post
        req.ContentType = "multipart/form-data; boundary=" & boundary
        req.AllowAutoRedirect = True


        'リクエスト内容は、いったん MemoryStream に入れておきます
        ' RequestStream に直接書き込んでも良いのですが、
        '  それだと、書き込んだ内容を後でチェックできないので、
        '  Byte() や MemoryStream を中継させた方がデバッグしやすいです。
        Dim reqData As New MemoryStream()

        Dim encUTF8 = System.Text.Encoding.UTF8
        Dim writer As New BinaryWriter(reqData, encUTF8)

        'ファイルパート
        writer.Write("--" & boundary & vbCrLf)
        writer.Write("Content-Disposition: form-data; name=""encoded_image""; filename=""" & pngImageFile & """" & vbCrLf)
        writer.Write("Content-Type: image/png" & vbCrLf)
        writer.Write(vbCrLf)

        Dim rawBin() As Byte = File.ReadAllBytes(pngImageFile)
        writer.Write(rawBin)
        writer.Write(vbCrLf)

        '表示言語パラメータ
        writer.Write("--" & boundary & vbCrLf)
        writer.Write("Content-Disposition: form-data; name=""hl""" & vbCrLf)
        writer.Write(vbCrLf)
        writer.Write("ja" & vbCrLf)

        'マルチパートの終端
        writer.Write("--" & boundary & "--")

        'MemoryStream の内容をフラッシュ(ADODB.Stream の Flush と同義)
        reqData.Flush()

        'ここからが本番
        Dim reqStream = req.GetRequestStream()

        'POST する要求ボディを書き込む
        reqData.Position = 0
        reqData.CopyTo(reqStream)
        reqStream.Flush()

        reqData.Dispose()   '書き込みは完了したので、MemoryStream はもう要らない
        reqStream.Close()   '要求ボディの書き込み終了。でも送信前なので Dispose しちゃ駄目。

        'いざ送信!
        Dim res = DirectCast(req.GetResponse(), HttpWebResponse)

        'サーバーから結果を受け取る
        Dim resStream = res.GetResponseStream()

        '応答ボディを、いったん MemoryStream に入れなおす
        Dim resData As New MemoryStream()
        resStream.CopyTo(resData)

        '要求ボディも応答ボディも、もう使わないので破棄
        reqStream.Dispose()
        resStream.Dispose()

        'レスポンスの文字コードを自動判定する必要がある場合の処理例
        '  今回の Yahoo API を使う場合には不要な判定処理かと思いますが一応
        Dim resEnc As System.Text.Encoding

        'ヘッダーに、「Content-Type: text/html; charset=Shift_JIS」などの
        '文字列が来ていないかチェックする
        Dim ct As String = res.Headers("Content-Type")
        Dim pos = Strings.InStr(ct, "charset=", CompareMethod.Text)
        If pos > 0 Then
            Dim enc = Strings.Mid(ct, pos + "charset=".Length)
            resEnc = System.Text.Encoding.GetEncoding(enc)
        Else
            'charset が不明な場合は推測するしかない
            '  下記では、とりあえず UTF-8 で代用していますが、時には
            '  Response Body のバイナリ内容から判定する必要があるかも
            resEnc = System.Text.Encoding.UTF8
        End If

        'MemoryStream のままだと Read しにくいので、
        '通常は BinaryReader なり StreamReader なりを併用します
        Dim reader As New StreamReader(resData, resEnc)

        '応答結果すべてを文字列として読み取る場合
        resData.Position = 0
        Dim responseText As String = reader.ReadToEnd()

        'バイナリとして取得
        resData.Position = 0
        Dim responseBinary() As Byte = resData.ToArray()

        resData.Dispose()   '読み込み終わったので、MemoryStream はもう要らない

        TextBox1.Text = responseText
    End Sub
End Class

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。