PHPでフォームを使わずにCSVファイルをPOST送信する方法
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 10K+
いつもお世話になっております。
標記の件について、HTMLで記述したフォームを利用してPOST送信することはできるのですが、
フォームを介さずに指定したURLでダウンロードできるCSVファイルを別のアップロード用URLに
POST送信したく、いろいろと調べてみたのですが、自己解決できなかったので、
こちらに聞きこみさせていただきました。
POST送信にはcURLを利用しています。
ちなみに、指定したURLからCSVファイルの情報を取得する部分までは、
以下のコードで特に問題なくできています。
$download_url = 'http://sample.com/download/';
$ch = curl_init($download_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
curl_close($ch);
$contentの中身を出力して、CSV形式のデータが表示されることは確認済みです。
そして、問題なのがPOST送信の方になります。
$upload_url = 'http://sample.com/upload/';
$header = array(
'Content-Type: multipart/form-data',
'Content-Length: ' . strlen($content), // ここは自信ないです。
);
$post_data = array(
'file' => $file, // ここに何を入れていいのかがよく分かっていません
);
$ch = curl_init($upload_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$response = curl_exec($ch);
curl_close($ch);
上記のコメントのところに書きましたように、アップロード側の受け入れ先の変数名である
「file」に何を入れたらよいのか分からなかったので、
試しにHTMLのフォームでファイルをPOSTした時の$_FILEを参考に以下のように書いてみましたが、
$file = array(
'name' => 'upload.csv',
'type' => 'text/csv',
'tmp_name' => $content, // ここに何を入れていいのかがよく分かっていません
'error' => 0,
'size' => strlen($content), // ここも自信ないです。
);
「tmp_name」のところは、フォームからアップロードした際の一時ファイルの
保存先のため、自分でもまず間違いだと思っています。
ただ、フォームを介さない場合のファイルデータの場合は、
何を入れるべきか見当がつかない状況です。
$post_data = array(
'file' => '@./upload.csv;filename=upload.csv;type=text/csv',
);
また、いろいろと検索している際、「file」の部分は上記のような記述方法を
見かけましたが、こちらも最初のファイル名は一時ファイルの保存先と思われるため、
結局何を入れるべきか分かりませんでした。
つきましては、フォームを介さずにCSVファイルをPOST送信する方法について、
ご教授いただければ幸いです。
「file」部分にこだわっていましたが、全く見当違いのことを調べているかも
知れませんし、他にもっとスマートな実装方法があれば、
PHPであれば特にcURLでのPOST送信にはこだわりません。
それでは、よろしくお願いいたします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
私自身は試していませんが、事例を見つけましたので参考にどうぞ。
seijimomoto.blogspot.com: PHP cURL関数でPOSTフィールドに配列データとファイルを同時に指定する
http://seijimomoto.blogspot.jp/2012/02/php-curlpost.html
[PHP] cURLのPOSTでファイルアップロードする方法 – 零弐壱蜂
http://b.0218.jp/20140117004504.html
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/01/11 15:37
ご提示していただいたURLを参考にして、改めて取得したCSVデータを
ファイルに格納して、そちらのパスを指定するようにして、
以下のように修正してみました。
※前回、省略した箇所も含めて追記しています。
```php
$download_url = 'http://sample.com/download/';
$ch = curl_init($download_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
curl_close($ch);
$filename = 'upload.csv';
$file_path = '/tmp/upload.csv';
file_put_contents($file_path, $content); // CSVファイルが生成されることは確認済みです。
$file_size = filesize($file_path); // テストしたファイルのサイズは8KBくらいです。
$upload_url = 'http://sample.com/upload/';
$header = array(
'Content-Type: multipart/form-data',
'Content-Length: ' . file_size,
'Authorization: Bearer <アクセストークン>', // こちらの認証については他の処理で成功しているので、特に問題ないと思います。
);
$post_data = array(
'type' => 1, // アップロード側で必要なリクエストパラメータ
'file' => "@{$file_path};filename={$filename};type=text/csv;size={$file_size}",
);
$ch = curl_init($upload_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$response = curl_exec($ch);
curl_close($ch);
```
上記のように修正したことにより、ひとまずPOST送信するところまでは
できたようですが、送信先でエラーが発生している状態です。
> 413 Request Entity Too Large
>
> The requested resource does not allow request data with POST requests,
> or the amount of data provided in the request exceeds the capacity limit.
上記のようなエラーメッセージが表示されてしまうのですが、
ファイルサイズ的には許可されている容量である100MBよりもはるかに軽い
8KBのファイルなので、何が原因なのか判別できずにいます。
つきましては、上記のソースとエラーメッセージから、
何か問題点や確認事項などが分かる方がいらっしゃれば、
ご教授をお願いいたします。
2016/01/11 15:47
送信元のサーバの設定とは無関係かもしれませんが、
ウェブサーバとして利用しているNginxの設定ファイルに
client_max_body_size 20M;
を追記して、更新しても状況は変わりませんでした。
2016/01/11 17:07
やってますかね? うーむ困りました。
Nginx での 413 Request Entity Too Large エラーの対処法 - Qiita
http://qiita.com/takecian/items/639deeae094466de6546
2016/01/11 18:01
service nginx reload
と
nginx -s reload
の両方で更新しましたが、状況は変わりませんでした。
記述場所がご提示いただいた場所と若干違ったので、
そちらも変えて試してみましたが、変わりませんでした。
ただ、このメッセージが出ているサーバは外部のものなので、
送信している自前のサーバの設定を変えても関係ないのかなとも
思っております。
送信先はYahoo!ストアのショッピング用APIで公開されている
URLなので、そちらのサーバの設定でサイズが絞られているとは
考え難い状況です。。。
2016/01/12 18:17
コマンドラインのcURLでいろいろとテストしてみたところ、
ヘッダーの「Content-Length」を入れない時に成功したので、
スクリプトの方も削除したところ、無事にアップロードができました。
なぜサイズを入れないと受け付けてくれないのかは、
アップロード側の仕様なのか謎のままなのですが。
あと、CSVファイルのMIME TYPEが間違っていたので修正しました。
(誤) text/csv
(正) text/comma-separated-values
ただ、こちらは下記の他、間違っている状態のままでも
アップロード自体は成功しました。
text/plain
application/vnd.ms-excel
最初はあまり重要視していなかったのですが、ファイル送信の時に
他のリクエストパラメータを含める場合は、
cURLでのオプションの指定も特殊なものになって、
スクリプトの書き方も工夫が必要だったのですが、
最初にm6uさんにご紹介していただいた1つ目の参考サイトを見て、
記述方法が分かったので、そちらでハマることがなかったのが
非常に助かりました。
この度はアドバイスいただき、ありがとうございました。
2017/05/18 18:02
同様の事を行いたくて、ぐぐったらこちらが引っかかったので参考にさせていただきました。
とても助かりました。ありがとうございました。
chapterさんがまとめてなかったら何時間もかかったと思います。。。
ヘッダーの「Content-Length」について報告ですが、
私の方では、ヘッダーの持ち方をポストデータと同じ持ち型にした所
うまく動きました。
$header = array(
'Content-Type'=>'multipart/form-data',
'Content-Length'=> $file_size,
);
ちゃんと追う余裕もなくて申し訳ないですが、、、
2017/06/09 19:04
お返事が遅くなってしまい、失礼しました。
ご参考になったようでよかったです。
また、フィードバックの方もありがとうございます。
先ほど、私が挙げたソースコードを見たところ、
$header = array(
'Content-Type: multipart/form-data',
'Content-Length: ' . file_size,
【以下省略】
のようになっており、「file_size」が変数として「$file_size」
と記述されていないのに気づきました。(汗)
単純な転記ミスだったかも知れませんが、実際にこの記述だったら
ファイルサイズでエラーが出るのは当然ですね。。。
時間に余裕ができたら、kihadaさんの記述の形も含めて、
ファイルサイズをちゃんと渡す方式でも試してみようと思います。