C++ Builder CE ネットワークプログラミング

TMultipartFormDataを使ってStreamをそのまま流し込んでDiscordwebhookを叩く

副題に記述したとおり、TMultipartFormDataへ直接AddStreamします。うまく動きますでしょうか?前記事

ではいつものIndyのTIdHTTPPOSTTIdMultiPartFormDataStreamを使いました。このクラスにはAddStreamのメソッドがありません。他方TMultipartFormDataにはAddStreamがありますので、使ってみようというのが本記事の趣旨です。何度かやってますが、TS-WLCEからGETしたストリームを一旦ファイルに落とすことなく、そのままPOSTする感覚ですね。少なくともディスクスペースの節約にはなります。C++ Builder CEのIDEを起動して、新規のVCLプロジェクトを作ります。次図のように、

TNetHTTPClientTNetHTTPRequestをフォームに置き、さらにTButtonx2(GetとPost)TEdit、TImage、TLabel、TMemoを配置します。次はコードです。

Unit1.hは、

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <System.Net.HttpClient.hpp>
#include <System.Net.HttpClientComponent.hpp>
#include <System.Net.URLClient.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TButton *Post;
	TButton *Get;
	TImage *Image1;
	TEdit *Edit1;
	TLabel *Label1;
	TNetHTTPClient *NetHTTPClient1;
	TNetHTTPRequest *NetHTTPRequest1;
	TMemo *Memo1;
	void __fastcall PostClick(TObject *Sender);
	void __fastcall GetClick(TObject *Sender);
	void __fastcall NetHTTPClient1AuthEvent(TObject * const Sender, TAuthTargetType AnAuthTarget,
          const UnicodeString ARealm, const UnicodeString AURL,
          UnicodeString &AUserName, UnicodeString &APassword, bool &AbortAuth,
          TAuthPersistenceType &Persistence);
	void __fastcall NetHTTPRequest1RequestCompleted(TObject * const Sender, IHTTPResponse * const AResponse);

private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Unit1.cppは、

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <System.Net.HttpClient.hpp>
#include <System.Net.HttpClientComponent.hpp>
#include <System.Net.URLClient.hpp>
#include <System.Net.Mime.hpp>

#include <Jpeg.hpp>

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

	TMemoryStream* ms = new TMemoryStream();

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{

	NetHTTPRequest1->Client = NetHTTPClient1;


}
//---------------------------------------------------------------------------


void __fastcall TForm1::PostClick(TObject *Sender)
{
	TMultipartFormData *formData = new TMultipartFormData(NULL);

	// Add fields to the form data
	formData->AddField("content", Edit1->Text);


	formData->AddStream("file", ms,"image/jpeg","nowhere.jpg");
    
	// Set the request method and URL
	NetHTTPRequest1->MethodString = "POST";
	NetHTTPRequest1->URL = "https://discord.com/api/webhooks/YourServer's ID/webhook_token";
	


	// Send the request with the multipart form data
	TMemoryStream *responseStream = new TMemoryStream();
	try
	{
		NetHTTPRequest1->Post(NetHTTPRequest1->URL, formData, responseStream);
		responseStream->Position = 0;
	//Memo1.Lines.LoadFromStream(ResponseContent, Encoding);
		Memo1->Lines->LoadFromStream(responseStream,TEncoding::UTF8);
	} catch (const Exception &E){
		ShowMessage(E.Message);
	}

		delete responseStream;
		delete formData;
}


void __fastcall TForm1::GetClick(TObject *Sender)
{
	String url = "http://192.168.0.112/snapshot.jpg";



	NetHTTPRequest1->Get(url,ms);
	ms->Position = 0;

	//ms->SaveToFile("test.jpg");
	//Image1->Picture->LoadFromFile("test.jpg");

	Image1->Picture->LoadFromStream(ms);
	ms->Position = 0;

	//httpRequest->Disconnect();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::NetHTTPClient1AuthEvent(TObject * const Sender, TAuthTargetType AnAuthTarget,
		  const UnicodeString ARealm, const UnicodeString AURL,
          UnicodeString &AUserName, UnicodeString &APassword, bool &AbortAuth,
          TAuthPersistenceType &Persistence)
{
 	if (AnAuthTarget == TAuthTargetType::Server) {
		AUserName = "your_id";
		APassword = "your_passwd";
	}

}
//---------------------------------------------------------------------------
void __fastcall TForm1::NetHTTPRequest1RequestCompleted(TObject * const Sender, IHTTPResponse * const AResponse)

{

	Label1->Caption = IntToStr(AResponse->StatusCode);

}
//---------------------------------------------------------------------------

エッセンシャルなID,Token,Passwordは変えてあります。動かすと、

“Get”してから“Post”するとこんな感じです。Discord側には、

こんな感じで新着します。

TNetHTTPClientTNetHTTPRequestの使い勝手は、TIdHTTPとはだいぶ違います。SSLのためのDLLが要らないのが長所かな。またClientとRequestの二つで一つなのも慣れないと違和感がありますかね。Debugどうするんだろうか?(お分かりの方はコメント願います。)

コメント