以前、記事の収集と画像の保存を実現する収集ツールを作成していました。記事の内容はデータベースに保存されます。そして写真は最初に画像サーバーにアップロードしてから、画像アドレスを返し、記事の画像アドレスを置き換える必要があります。
ここで問題が発生します。すべてが正常に収集できましたが、ローカル テストは正常で、写真も正常にアップロードできましたが、本番環境には写真がありません。その後、段階的にデバッグしたところ、データが次のとおりであることがわかりました。そこにありますが、写真が本番環境に正常にアップロードされなかったのはなぜですか?
数日間苦労した後、コードを段階的に読み、デバッグし、Baidu を使用した後、ついに答えを見つけました。なんと大きな落とし穴でした。curl postを使用して画像サーバーにアップロードします
PHP の cURL は、
を介した POST リクエストをサポートします。 CURL_POSTFIELDS
传递关联数组(而不是字符串)来生成multipart/form-data
+完全なファイル パス」の構文を使用することにより、ファイルの添付をサポートしていました。これは、コマンド ラインから cURL プログラムを直接呼び出すための構文と一致しています: @
リーリー
構文の代わりに CURLFile を使用することをお勧めします: @
リーリー
構文を拒否させ、CURLFile スタイルのファイルのみを受け入れるように強制できる CURL_SAFE_UPLOAD
选项,可以强制PHP的cURL模块拒绝旧的@
オプションも導入されています。デフォルト値は、5.5 の場合は false、5.6 の場合は true です。
しかし、落とし穴は次のとおりです: @
语法在5.5就已经被打了deprecated,在5.6中就直接被删除了(会产生 ErorException: The usage of the @filename
この構文は 5.5 で非推奨となり、5.6 では直接削除されました (ElorException が生成されます: ファイルのアップロードに対する @filename
API の使用は非推奨です。使用してください)代わりに CURLFile クラスを使用します)。
PHP 5.6 以降の場合、CURL_SAFE_UPLOAD
を false に手動で設定することは 無意味です。これは、文字通り「false に設定すると安全でない古いメソッドが有効になる」とは理解されていません。古いメソッドは廃止された構文として完全に存在しなくなりました。 PHP 5.6+ == CURLFile のみ。幻想を抱かないでください。
私のデプロイメント環境は 5.4 (@
Syntax のみ) ですが、私の開発環境は 5.6 (CURLFile のみ) です。どちらも、両方がサポートする移行バージョンである 5.5 には焦点を当てていないため、環境判断を備えた 2 セットのコードを作成する必要があります。
ここで問題が起こります...
この種の環境判定コードを見たことがあります:
リーリーこの種のコードを評価するには、クソという一言しかありません。
この判断は、典型的な マジックナンバーの罠に陥ります。コード内にバージョン番号が不可解に表示されるため、PHP マニュアルや更新履歴を長時間確認しないと、作成者がどの機能変更に引っかかっているのかを理解するのは困難です。
コードはそのルーツに戻る必要があります。実際のニーズは、従来の @
構文に戻らずに、最初に CURLFile を使用することです。コードは次のとおりです:
信頼性の高い観点から、古い CURL_SAFE_UPLOAD
的值,明确告知php是容忍还是禁止旧的@
语法。注意在低版本PHP中CURLOPT_SAFE_UPLOAD
構文を許容するか禁止するかを PHP に明確に伝えるために
CURLOPT_SAFE_UPLOAD
定数自体が存在しない可能性があるため、以下を判断する必要があることに注意してください:
curl_setopt()
单发还是curl_setopt_array()
バッチに関係なく、cURL のオプションは常に 1 つずつ有効になり、設定されたオプションは後続のオプションを設定するときに cURL の動作にすぐに影響します。
たとえば CURLOPT_SAFE_UPLOAD
就和CURLOPT_POSTFIELDS
的行为有关。如果先设置CURLOPT_POSTFIELDS
再设置CURLOPT_SAFE_UPLOAD
の場合、後者の制約は有効になりません。なぜなら、前者を設定すると、cURL はデータの実際の読み取りと処理をすでに完了しているからです。
CURL にはこの落とし穴があるオプションがいくつかあるので注意してください。幸いなことに、この種の「依存関係」には選択肢は多くなく、仕組みも複雑ではないため、簡単に扱うことができます。私の方法は、最初にすべてのオプションをバッチ設定してから curl_exec()
的前一刻才用curl_setopt()
单发设置CURLOPT_POSTFIELDS
まで待つことです。
実際、curl_setopt_array()
で使用される配列では、後ろの CURLOPT_POSTFIELDS
の位置も信頼できることが保証されています。 curl_setopt_array()
用的数组中,保证CURLOPT_POSTFIELDS
的位置在后边也是可靠的。PHP的关联数组是有顺序保障的,我们也可以假设curl_setopt_array()
内部的执行顺序一定是从头到尾按顺序[注A]
PHP の連想配列は順序が保証されています
curl_setopt_array()
の内部実行順序は、[Note A]
の最初から最後まで順番である必要があると仮定することもできます。安心してご利用いただけます。 私のアプローチは、コードのパフォーマンスにさらなる保険を追加し、将来の不正行為を防ぐための順序の重要性を強調することです。 🎜
PHP バージョン 5.2 以下には名前空間がありません。コード内でスペース区切り文字 が使用されている場合、パーサー エラーが発生します。 PHP 5.2 を扱うのは実際には簡単で、名前空間を放棄するだけです。
注意する必要があるのは、名前空間を備えた PHP 5.3 以降です。 CURLFile を呼び出す場合でも、class_exists()
判断CURLFile的存在性,都推荐写成CURLFile
でトップレベルのスペースを明示的に指定する場合でも、名前空間でラップされたときにコードがクラッシュするのを防ぎます。
さて、この穴はかなり深いので、飛び出したらシェアします
(上記の解決策はウェブサイトから転載したものです。記事を見つけてくれてありがとう!)
。