非表示のiframeでの非同期画像読み込み:落とし穴

最近、サーバーで写真アップローダーをしなければなりませんでした。 サードパーティのスクリプトの使用経験があり、多くの場合、最初からスクリプトを完成させる時間があるため、ブートローダーを自分で作成することにしました。



Googleにアクセスすると、iframeを介したファイルのダウンロードに関する多くの記事が提供されます。 アルゴリズムは一般的に次のようになります:

1)非表示のフレームを作成します(通常、幅と高さはHTMLおよびCSSプロパティを介して単純に無効化されます)

2)フレームの名前にフォームのアクションを設定します。

3)ファイルを送信します。 喜ぶ。



使いやすくするために、個別の「ダウンロードの開始」ボタンは作成されませんでしたが、ファイル入力用のonChangeハンドラーがハングアップしました。





さらなるテスト:Chrome 9,10,11; Firefox 3.6(4番目はまだリリースされていません); Opera 9,10,11; IE 7との互換モードを含むIE 6およびIE8。Chrome、Opera、FFはLinuxとWindowsの両方でテストされました。 飛行は正常で、テストチームは合格しました。 サイトのライブバージョンに送信します。



この瞬間から、とても楽しいことが始まりました。 このサイトには1日に数千人の訪問者がいます。 そして、そのうちの6人がテクニカルサポートに、写真をアップロードする新しい方法が機能しないと書いています。 エラー警告をスクリプトに追加し、サーバーにログを記録した後、スクリプトは実際には数百人に対して機能しなかったことが判明しました。



最初に見つかった不具合はIE 7にありました。それは、onChangeイベントハンドラーに関するものでした。 判明したように、これは既知のバグです-IE7でDOMツリーを変更すると、onChangeが呼び出されます。 その中で、JSコードはHTMLドキュメントの構造を変更します。 これは再びonChangeを呼び出します。 つまり 競合状態が判明し、IE7は変更を無視し、空のファイル名を送信します。 解決策:setTimeoutの関数で呼び出しをラップします。 このメソッドは、テストされたすべてのブラウザーで正しく機能します。



鼻をハックするままです:互換モードのIE 7とIE 8は完全に異なるブラウザーです...



次の非常に興味深いバグはOpera 11にあり、ユーザーは3人しかいませんでした。 おそらく、オペラ自体が原因ではなく、何らかの補助ソフトウェアが原因だったのでしょう。 実際には、アプリケーション/ jsonではなく、mimeタイプtext / htmlを使用してサーバーからJSON応答を送信する必要があります。 iframeでタイプapplication / jsonでデータを開こうとすると、一部のブラウザーはユーザーにバイナリファイルをダウンロードするよう提案しましたが、JavaScriptで静かに処理する必要があります。



OperaはネイティブHTMLが送信されていることを認識しています。バナーを表示してみませんか? 押し込んだ。 当然、そのような文字列をダイジェストしようとすると、パーサーは崩壊しました。 解決策:第一に、テキスト/プレーンを使用することが望ましいです。第二に、開き中括弧と閉じ中括弧の最初の出現に従って行トリミングが追加されました。



3番目のグリッチは最悪でした。 ほとんどの場合、Firefox、IE、Chromeで現れます。 データは非表示のiframeではなく、新しいタブに送信されました。 もちろん、ファイルはサーバーに転送されました。 ただし、JSは別のタブに移動できなかったため、データは表示されず、使用できませんでした。



最悪なことに、このバグを繰り返すことはできませんでした-チームのマシン上のIEでさえもうまくいきました。 フレームの表示/非表示のさまざまな方法が使用されたテストページが作成されました。 予想どおり、可視フレームは正しく機能し、非表示フレームはタブを作成しました。 解決策は簡単でした-表示されたフレームを非表示のdivにフレームする必要があります(表示:なし)。



また、スクリプトの作成段階でもキャッチできた不具合についても少し説明します。



それとは別に、クロッパー(画像の特定の領域を選択するためのフレーム)で歪みを処理する必要がありました。 このスクリプトはサードパーティ製でした。 静止画像を使用すると、すべてが突然作動しました。 しかし、画像が作成されるとすぐに、間違ったサイズから完全なシェーディングまで、さまざまな不具合が動的に発生しました。 delete / newを使用してオブジェクトを再作成しても役に立ちませんでした。 試行錯誤により、イメージが完全にロードされた後にスクリプトを初期化する必要があることが判明しました。 また、パラメーターを再読み取りするために、リセットメソッドがあります。 唯一の方法であり、他の方法はありません!



最も不快な問題の1つは、交差するフォーム(たとえば、フォーム内のフォーム)がサーバーに送信されない場合があることです。 そして、ファイル入力はフォーム要素です。 頭に浮かぶ最初の解決策は、入力からデータをコピーし、別の場所に同様のDOMツリーを作成することです。 しかし、これはすべてのブラウザーでサポートされているわけではありません。 DOMツリーを介した入力の転送も失敗しました。 しかし、DIVでフレーム化すると、フォーム要素とともに静かに移動できます。



ところで、要素の動的作成について。 スクリプトの最終バージョンでは、フォームが動的に作成され、ページ上部の非表示レイヤーに配置されます。 これにより、フォームの交差が回避され、多数のフォームローダーを簡単に作成できるようになりました。 しかし、iframeを動的に作成することはできませんでしたが、ついに自分の目で、新しいタブを開くことによる不具合を目にしました。



結論として、私たちは自分でスクリプトを開発する決定を後悔しなかったと言います。 個人的には、バグを捕まえるときに多くの経験と楽しい瞬間を得ました。時にはヒステリーや血まみれの涙が楽しめます。 しかし、結果はまさにあなたが必要とするものです。



All Articles