質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

Q&A

解決済

1回答

3172閲覧

C#のwebRequestで複数のファイルをPOST送信したい。

s.s

総合スコア13

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

0グッド

0クリップ

投稿2022/06/03 04:31

編集2022/06/06 00:13

http://xxxx.xxx.xx.xx/filedataへ複数のファイル送信を行いたいのですが、うまくいきません。

以下のサイトを参考にしました。
https://ouipanda.hatenablog.com/entry/20090716/1247757511

データ受信側はDjangoRestFrameWorkで作成されています。

Postmanでhttp://xxxx.xxx.xx.xx/filedataへfomr-dataのkeyとValueを設定し、POSTしたところなんの問題もなく
送信&受信する事が出来ました。

パラメータはこんな感じです。
{
"id": "",
"title": "",
"pdf_file": "",
"csv_file": "",
}

ファイルを一つだけPOSTする場合は問題なく行えるのですが二つともファイルを送るとなると上手く行きません。

↓実際のコード

string url = "http://localhost:8000/api/filedata/"; List<string> files = new List<string>(); files.Add("C:\\file\TEST_BOOK1.csv"); files.Add("C:\\file\TEST.pdf"); List<string> fileNames = new List<string>(); fileNames.Add("pdf_file"); fileNames.Add("csv_file"); string tick = Environment.TickCount.ToString(); System.Text.Encoding enc = System.Text.Encoding.UTF8; WebRequest req = WebRequest.Create(url); req.Method = "POST"; req.ContentType = "multipart/form-data; boundary=" + tick; byte[] boundary = enc.GetBytes("--" + tick); byte[] crlf = enc.GetBytes("\r\n"); List<byte[]> headers = new List<byte[]>(); string header = ""; //ヘッダの作成とデータサイズの計算 long contentLen = 0; for (int i = 0; i < files.Count; i++) { //ヘッダ header = "--" + tick + "\r\n" + "Content-Disposition: form-data; name=\"" + fileNames[i] + i.ToString() + "\"; filename=\"" + Path.GetFileName(files[i]) + "\"\r\n" + "Content-Type: application/octet-stream\r\n" + "Content-Transfer-Encoding: binary\r\n\r\n"; headers.Add(enc.GetBytes(header)); //1ファイルごとのデータサイズ contentLen += headers[i].Length + new FileInfo(files[i]).Length; } //全体のデータサイズ req.ContentLength = contentLen + ((boundary.Length + crlf.Length + crlf.Length) * files.Count) + boundary.Length; //送信 using (Stream reqStream = req.GetRequestStream()) { for (int i = 0; i < files.Count; i++) { //送信ファイル using (FileStream fs = new FileStream(files[i], FileMode.Open, FileAccess.Read)) { //ヘッダ reqStream.Write(boundary, 0, boundary.Length); reqStream.Write(crlf, 0, crlf.Length); reqStream.Write(headers[i], 0, headers[i].Length); //ファイル内容 byte[] buf = new byte[0x1000]; int readSize = 0; while (true) { readSize = fs.Read(buf, 0, buf.Length); if (readSize == 0) break; reqStream.Write(buf, 0, readSize); } reqStream.Write(crlf, 0, crlf.Length); } } reqStream.Write(boundary, 0, boundary.Length); WebResponse res = req.GetResponse(); } }

追記

上手く行かない→

--boundary Content-Disposition: form-data; name="フォーム1"; filename="ファイル1" Content-Type: application/octet-stream Content-Transfer-Encoding: binary --boundary Content-Disposition: form-data; name="フォーム2"; filename="ファイル2" Content-Type: application/octet-stream Content-Transfer-Encoding: binary

というようにヘッダーの内容を記述し、送信したときに。
フォーム1に指定のファイルがPOSTされることは確認できるのですが、フォーム2へのPOSTが確認できない。
フォーム2への送信処理がとばされているのかと思ったのですが、Fiddlerを使い、内容を確認したところそういうわけでは無さそうです。

Postmanで送信したときの内容とプログラムから送信したときの内容を見比べてみました。
同じcsvファイルをPOSTしているのは確認がしやすいようにです、ファイル形式が違うため上げることが出来ないなどはありません。

Postmanの方は末尾に"--"が付いていますが、これは処理に関係あるのでしょうか?

以下 プログラムから送信したときの内容

--96403343 Content-Disposition: form-data; name="title" テスト --96403343 Content-Disposition: form-data; name="user" test --96403343 Content-Disposition: form-data; name="category" 1 --96403343 Content-Disposition: form-data; name="checked" False --96403343 Content-Disposition: form-data; name="pdf_file"; filename="Book1.csv" Content-Type: application/octet-stream Content-Transfer-Encoding: binary 11818818 18118 99999 --96403343 Content-Disposition: form-data; name="csv_file"; filename="Book1.csv" Content-Type: application/octet-stream Content-Transfer-Encoding: binary 11818818 18118 99999 --96403343

以下Postmanから送信したときの内容

----------------------------228829904362102449550779 Content-Disposition: form-data; name="title" test114 ----------------------------228829904362102449550779 Content-Disposition: form-data; name="csv_file"; filename="Book1.csv" Content-Type: text/csv 11818818 18118 99999 ----------------------------228829904362102449550779 Content-Disposition: form-data; name="pdf_file"; filename="Book1.csv" Content-Type: text/csv 11818818 18118 99999 ----------------------------228829904362102449550779--

コードの方も少し変えました

//送信先のURL string url = "http://localhost:8000/api/filedata/"; //送信対象のCSVファイルのパスと名前 string filePath = "C:\\tmp_file\\nest1\\Book1.csv"; string fileName = Path.GetFileName(filePath); //送信対象のPDFファイルのパスと名前 string pdffilePath = "C:\\tmp_file\\nest1\\Book1.csv"; string pdffileName = Path.GetFileName(pdffilePath); //パラメータ設定 string title = "テスト"; string user = "test"; // int category = 1; bool check = false; // string tick = Environment.TickCount.ToString(); System.Text.Encoding enc = System.Text.Encoding.UTF8; //WebRequestの生成 WebRequest req = WebRequest.Create(url); req.Method = "POST"; req.ContentType = "multipart/form-data; boundary=" + tick; byte[] boundary = enc.GetBytes("--" + tick); byte[] crlf = enc.GetBytes("\r\n"); List<byte[]> headers = new List<byte[]>(); //全体のヘッダー string postheader = "--" + tick + "\r\n" + "Content-Disposition: form-data; name=\"title\"\r\n\r\n" + title + "\r\n" + "--" + tick + "\r\n" + "Content-Disposition: form-data; name=\"user\"\r\n\r\n" + user + "\r\n" + "--" + tick + "\r\n" + "Content-Disposition: form-data; name=\"category\"\r\n\r\n" + category + "\r\n" + "--" + tick + "\r\n" + "Content-Disposition: form-data; name=\"checked\"\r\n\r\n" + check + "\r\n"; //ヘッダの作成とデータサイズの計算 long contentLen = 0; contentLen += enc.GetBytes(postheader).Length; string pdfheader = "Content-Disposition: form-data; name=\"pdf_file\"; filename=\"" + pdffileName + "\"\r\n" + "Content-Type: text/csv\r\n\r\n"; contentLen += boundary.Length + crlf.Length + enc.GetBytes(pdfheader).Length + new FileInfo(pdffilePath).Length + crlf.Length; string csvheader = "Content-Disposition: form-data; name=\"csv_file\"; filename=\"" + fileName + "\"\r\n" + "Content-Type: text/csv\r\n\r\n" + "--" + tick + "--\r\n"; contentLen += boundary.Length + crlf.Length + enc.GetBytes(csvheader).Length + new FileInfo(filePath).Length;// + crlf.Length; //全体のデータサイズ req.ContentLength = contentLen + boundary.Length; //送信 using (Stream reqStream = req.GetRequestStream()) { //全体のヘッダ reqStream.Write(enc.GetBytes(postheader), 0, enc.GetBytes(postheader).Length); using (FileStream pdfFs = new FileStream(pdffilePath, FileMode.Open, FileAccess.Read)) { //pdf部ヘッダ reqStream.Write(boundary, 0, boundary.Length); reqStream.Write(crlf, 0, crlf.Length); reqStream.Write(enc.GetBytes(pdfheader), 0, enc.GetBytes(pdfheader).Length); //ファイル内容 byte[] pdfbuf = new byte[0x1000]; int pdfreadSize = 0; while (true) { pdfreadSize = pdfFs.Read(pdfbuf, 0, pdfbuf.Length); if (pdfreadSize == 0) break; reqStream.Write(pdfbuf, 0, pdfreadSize); } reqStream.Write(crlf, 0, crlf.Length); } using (FileStream csvFs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { //csv部ヘッダ reqStream.Write(boundary, 0, boundary.Length); reqStream.Write(crlf, 0, crlf.Length); reqStream.Write(enc.GetBytes(csvheader), 0, enc.GetBytes(csvheader).Length); //ファイル内容 byte[] csvbuf = new byte[0x1000]; int csvreadSize = 0; while (true) { csvreadSize = csvFs.Read(csvbuf, 0, csvbuf.Length); if (csvreadSize == 0) break; reqStream.Write(csvbuf, 0, csvreadSize); } reqStream.Write(crlf, 0, crlf.Length); }   reqStream.Write(boundary, 0, boundary.Length);

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/06/03 07:37 編集

「うまくいきません」と言うだけでは情報不足です。具体的にどのような結果になるのかを書いてください。 Postman で期待通りの結果になるなら、Fiddler を使ってその時の要求ヘッダ・コンテンツがどのようになっているかと、「うまくいきません」という場合とを比較してみてはいかがですか。そこに解決のためのヒントが見つかるのではないかと思います。
退会済みユーザー

退会済みユーザー

2022/06/03 05:03

WebRequest の使用は必須ですか? HttpClient を使うことはできますか?
退会済みユーザー

退会済みユーザー

2022/06/03 06:51

> Postmanの方は末尾に"--"が付いていますが、これは処理に関係あるのでしょうか? ざっと見た限りでは気になる違いはそこぐらいでしょうか。 仕様かどうか、それが影響しているのかどうかは分かりませんが、自分がブラウザ (Chrome)、HttpClient、および https://dobon.net/vb/dotnet/internet/webrequestpost.html を参考に作った HttpWebRequest / HttpWebResponse を使ったコードでは一番最後の boundary には末尾に -- を追加しています。
s.s

2022/06/03 07:20

ありがとうございます、無事解決する事が出来ました。 SurferOnWwwさんから”Fidller を使って~”という提案があったおかけです、何をしているか(送っているか)という詳細を知るのは重要ですね・・・勉強になりました。
退会済みユーザー

退会済みユーザー

2022/06/03 09:01

HttpClient を使うと自分でコードを書いて boundary を設定する必要ななく、自動的にやってくれます。次の機会には HttpClient の使用を検討されてはいかがでしょう。
s.s

2022/06/06 00:14

そのような方法もあるのですね、自分の勉強不足を痛感致します・・・ この度は有難うございました。
guest

回答1

0

自己解決

すみません、自己解決しました。
末尾に"--"を追加したところ何の問題もなく複数ファイルのPOSTができるようになりました。
SurferOnWwwさん、ありがとうございました。Fidllerの存在を知らなかったので、助かりました。

投稿2022/06/03 06:54

s.s

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問