[delphi-users:4822] TRESTRequestでファイルのアップロード

337 views
Skip to first unread message

赤推

unread,
Jan 25, 2018, 4:50:25 AM1/25/18
to delphi...@freeml.com
こんにちは。
現在Delphi10.2のRESTで遊んでいます。

とあるシステムにファイルをアップロードしたいのですが、Indyでいうところの
var
Ret:String;
begin
Ret:=IdHTTP1.Post(TIdURI.URLEncode('http://hogehoge.com/Service/UploadFileP2?FileName='+ExtractFileName(FileName)),FileName);
と同等のことをTRESTRequestで行いたいのですがどうすれば良いのでしょうか?
RESTRequest1.AddFile(AFileName);
RESTRequest1.Execute;
だと、ctMULTIPART_FORM_DATAとなって、正しいデータがアップロードされませ
ん。

よろしくお願いします。

赤推


MLホームページ: https://www.freeml.com/delphi-users

----------------------------------------------------------------------
Powered by freeml -- https://www.freeml.com/ --
------------------------------------------------------[freeml byGMO]--

あなたの街のチラシがいつでも無料で見放題!
チラシをクリックしてチラシが拡大されたらポイントゲット♪
まずはかんたん登録♪ -ポイントタウン-
https://www.pointtown.com/ptu/rd.cgi?cid=8912
----------------------------------------------------------------------

dacho

unread,
Jan 25, 2018, 5:07:55 AM1/25/18
to delphi...@freeml.com
こんにちは。

> RESTRequest1.AddFile(AFileName);

第2パラメータでタイプの指定が必要ではないでしょうか。

赤推

unread,
Jan 25, 2018, 5:51:12 AM1/25/18
to delphi...@freeml.com
 赤推です。こんにちは。


>> RESTRequest1.AddFile(AFileName);
>
>第2パラメータでタイプの指定が必要ではないでしょうか。

ファイルは色々なパターンがあるのですが、どのタイプを指定すれば良いのでし
ょうか?オールマイティーなものがありますか?

赤推

dacho

unread,
Jan 25, 2018, 6:17:57 AM1/25/18
to delphi...@freeml.com
個人的には形式の定まっていないデータは経験ないのですが、
ソースを見ると TParseApi や TKinveyApi では形式不明の場合は
ctAPPLICATION_OCTET_STREAM が使われていますね。
これで試されてはいかがでしょうか。

赤推

unread,
Jan 25, 2018, 6:37:32 PM1/25/18
to delphi...@freeml.com
 赤推です。何度もありがとうございます。

>個人的には形式の定まっていないデータは経験ないのですが、
>ソースを見ると TParseApi や TKinveyApi では形式不明の場合は
>ctAPPLICATION_OCTET_STREAM が使われていますね。
>これで試されてはいかがでしょうか。

これでやってみたのですが、相変わらずです。元ファイルの前後に余計なものが
ついてしまいます。

----------012618082938522
Content-Disposition: form-data; name="file"; filename="****.xml"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

<?xml version="1.0"?>
<APIResult xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
(元ファイルの中身)
----------012618082938522--

ちなみにctAPPLICATION_OCTET_STREAMをつけないと、Content-Typeが拡張子で判
断されてつくようです。Content-Type: text/xml

再度整理しますと、私の希望は(元ファイルの中身)の部分だけをPostしたいの
です。
よろしくお願いします。

赤推

赤推

unread,
Jan 25, 2018, 7:39:57 PM1/25/18
to delphi...@freeml.com
 赤推です。
 元ファイルの中身が間違ってたので修正します。

----------012618082938522
Content-Disposition: form-data; name="file"; filename="****.xml"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

(元ファイルの中身)
----------012618082938522--

dacho

unread,
Jan 26, 2018, 2:18:21 AM1/26/18
to delphi...@freeml.com
>これでやってみたのですが、相変わらずです。元ファイルの前後に余計なものが
>ついてしまいます。
>
>----------012618082938522
>Content-Disposition: form-data; name="file"; filename="****.xml"
>Content-Type: application/octet-stream
>Content-Transfer-Encoding: binary
>
><?xml version="1.0"?>
><APIResult xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.
>w3.org/2001/XMLSchema-instance">
>(元ファイルの中身)
>----------012618082938522--

バウンダリが処理されてないということでしょうか。
RESTRequest1.ContentType は何か設定していますか?
Execute の前に ShowMessage(RESTRequest1.ContentType) としたら
何が表示されますか?

赤推

unread,
Jan 26, 2018, 3:44:34 AM1/26/18
to delphi...@freeml.com
 赤推です。何度もありがとうございます。


>>----------012618082938522
>>Content-Disposition: form-data; name="file"; filename="****.xml"
>>Content-Type: application/octet-stream
>>Content-Transfer-Encoding: binary
>>
>><?xml version="1.0"?>
>><APIResult xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://
>>www.
>>w3.org/2001/XMLSchema-instance">
>>(元ファイルの中身)
>>----------012618082938522--
>
>バウンダリが処理されてないということでしょうか。

ファイル受信システムが受け取った結果ですが(テストではxmlファイルを送信
しています)、TIdHTTP.Postでやると(元ファイルの中身)に相当するxmlファ
イルができています(正常)。TRESTRequest.AddFileしてTRESTRequest.Execute
すると、上記のように(元ファイルの中身)の前後にファイル以外の部分が含ま
れた形でファイルができています(異常、元ファイルよりファイルサイズが大き
い)。
TIdHTTPもTRESTRequestもプロパティは特に変更していません。


>RESTRequest1.ContentType は何か設定していますか?
これはデフォルトのままです。オブジェクトインスペクタに表示されません。

>Execute の前に ShowMessage(RESTRequest1.ContentType) としたら
>何が表示されますか?
RESTRequest1.ContentTypeはTRESTContentTypeなので、ShowMessage(IntToStr
(Ord(RESTRequest1.ContentType))) としたら58です。ctMULTIPART_FORM_DATAの
ようです。

赤推

dacho

unread,
Jan 26, 2018, 4:16:33 AM1/26/18
to delphi...@freeml.com
>>RESTRequest1.ContentType は何か設定していますか?
>これはデフォルトのままです。オブジェクトインスペクタに表示されません。
>
>>Execute の前に ShowMessage(RESTRequest1.ContentType) としたら
>>何が表示されますか?
>RESTRequest1.ContentTypeはTRESTContentTypeなので、ShowMessage(IntToStr
>(Ord(RESTRequest1.ContentType))) としたら58です。ctMULTIPART_FORM_DATAの
>ようです。

すみません、RESTRequest.ContentType ではなくて RESTClient.ContentType
の間違いでした。
RESTClient.ContentType と RESTRequest.AddFile の ContentType が
適切な組み合わせではないのではと思ったのですが。

>(Ord(RESTRequest1.ContentType))) としたら58です。ctMULTIPART_FORM_DATAの
>ようです。

これだと恐らく RESTClient.ContentType も 'multipart/form-data'
になっているのだろうなと思います。

となると、サーバー側がどのようになっているのかというのも
気になりますが・・・
例えば
RESTClient.ContentType = 'application/x-www-form-urlencoded';
RESTRequest1.AddFile(AFileName, ctTEXT_PLAIN);
とした場合どうなりますか?

赤推

unread,
Jan 26, 2018, 4:51:38 AM1/26/18
to delphi...@freeml.com
 赤推です。

>すみません、RESTRequest.ContentType ではなくて RESTClient.ContentType
>の間違いでした。
>RESTClient.ContentType と RESTRequest.AddFile の ContentType が
>適切な組み合わせではないのではと思ったのですが。

Executeの前でShowMessage(IntToStr(Length(RESTResponse1.Content)))をやる
と0です。ブランクです。


>例えば
>RESTClient.ContentType = 'application/x-www-form-urlencoded';
>RESTRequest1.AddFile(AFileName, ctTEXT_PLAIN);
>とした場合どうなりますか?

----------012618184907390
Content-Disposition: form-data; name="file"; filename="****.xml"
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: binary

(元ファイルの中身)

----------012618184907390--
となりました。

赤推

dacho

unread,
Jan 26, 2018, 5:51:21 AM1/26/18
to delphi...@freeml.com
>>すみません、RESTRequest.ContentType ではなくて RESTClient.ContentType
>>の間違いでした。
>>RESTClient.ContentType と RESTRequest.AddFile の ContentType が
>>適切な組み合わせではないのではと思ったのですが。
>
>Executeの前でShowMessage(IntToStr(Length(RESTResponse1.Content)))をやる
>と0です。ブランクです。

RESTResponse じゃなくて RESTClient です。


>>例えば
>>RESTClient.ContentType = 'application/x-www-form-urlencoded';
>>RESTRequest1.AddFile(AFileName, ctTEXT_PLAIN);
>>とした場合どうなりますか?
>
>----------012618184907390
>Content-Disposition: form-data; name="file"; filename="****.xml"
>Content-Type: text/plain; charset="us-ascii"
>Content-Transfer-Encoding: binary
>
>(元ファイルの中身)
>
>----------012618184907390--
>となりました。

AddFileしたら multipart/form-data になってしまうようですね。
それにしてもサーバー側が気になりますが。

ファイルの中身をStringに読み込んで
RESTClient.ContentType := 'application/x-www-form-urlencoded';
RESTRequest1.Method := TRESTRequestMethod.rmPOST;
RESTRequest1.AddBody(data, ctTEXT_PLAIN);
のようにしたらmultipartにならないのではないかと思いますが。

赤推

unread,
Jan 26, 2018, 7:51:40 AM1/26/18
to delphi...@freeml.com
 赤推です。

>RESTResponse じゃなくて RESTClient です。
失礼しました。


>ファイルの中身をStringに読み込んで
>RESTClient.ContentType := 'application/x-www-form-urlencoded';
>RESTRequest1.Method := TRESTRequestMethod.rmPOST;
>RESTRequest1.AddBody(data, ctTEXT_PLAIN);
>のようにしたらmultipartにならないのではないかと思いますが。
試してみます。

残念ながら2/4まで出張で、返事ができるのが最短で2/5になってしまいます。
その時にまたご都合が合えば、お相手していただけるとうれしいです。

赤推

赤推

unread,
Feb 6, 2018, 2:13:18 AM2/6/18
to delphi...@freeml.com
 赤推です。結論としてはおかげさまで解決しました。

>>Executeの前でShowMessage(IntToStr(Length(RESTResponse1.Content)))をやる
>>と0です。ブランクです。
>
>RESTResponse じゃなくて RESTClient です。

RESTClientのContentTypeもブランクでした。


>>>例えば
>>>RESTClient.ContentType = 'application/x-www-form-urlencoded';
>>>RESTRequest1.AddFile(AFileName, ctTEXT_PLAIN);
>>>とした場合どうなりますか?

Content-Transfer-Encodingが変わるくらいで、マルチパートであることは同じ
です。


>ファイルの中身をStringに読み込んで
>RESTClient.ContentType := 'application/x-www-form-urlencoded';
>RESTRequest1.Method := TRESTRequestMethod.rmPOST;
>RESTRequest1.AddBody(data, ctTEXT_PLAIN);
>のようにしたらmultipartにならないのではないかと思いますが。

これでいけました。アップするファイルはバイナリもあるので、実際には
TMemoryStreamに読み込んで、
RESTRequest1.AddBody(Stream,ctAPPLICATION_OCTET_STREAM);
としました。ctTEXT_PLAINでも挙動は同じです。
RESTClient.ContentTypeは設定しなくても変わりませんでした。
RESTRequest1.AddBody(Stream) は試していたのですが、第二パラメータを設定
するのは思いつきませんでした。

ありがとうございました。

赤推
Reply all
Reply to author
Forward
0 new messages