タイトル : 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 |