まず、この図を使用して、非同期ファイルアップロードを実現する方法を説明します。
ごめんなさい。ドメインの1つをシャットダウンしましたが、イメージが消えました。それは本当に素敵なイメージでした。これは、Stack OverflowがImgurを介して画像をアップロードできることを知る前でした。
ご覧のとおり、コツは、ページ自体ではなく、非表示のIFRAME要素にHTTP応答を読み込ませることです。 (これは、JavaScriptを使用してFORMを送信するときに、FORM要素のtarget
プロパティを設定することによって行われます。)
これは機能します。ただし、私が直面している問題は、サーバー側のスクリプトが異なるドメインにあることです。 FORM-submitは、クロスドメインHTTPリクエストです。これで、サーバー側スクリプトでCORSが有効になり、私のWebページに、自分のページからそのスクリプトに対して作成されたHTTPリクエストの応答データを読み取る権限を付与します。ただし、これは、Ajax経由でHTTP応答を受け取った場合にのみ機能します。 ergo、JavaScript。
ただし、この場合、応答はIFRAME要素に向けられます。 XML応答がIFRAMEに到達すると、そのURLは削除スクリプトになります。 http://remote-domain.com/script.pl
。
残念ながら、CORSはこのケースをカバーしていません(少なくとも私は思う)-そのURLがページのURL(異なるドメイン)と一致しないため、IFRAMEのコンテンツを読み取ることができません。私はこのエラーを受け取ります:
安全でないJavaScriptが、URL hxxp://my-domain.com/outer.htmlのフレームからURL hxxp://remote-domain.com/script.plのフレームにアクセスしようとしました。ドメイン、プロトコル、ポートが一致している必要があります。
また、IFRAMEのコンテンツはXMLドキュメントであるため、postMessage
などを利用できるJavaScriptコードはIFRAME内にはありません。
だから私の質問は:IFRAMEからXMLコンテンツを取得するにはどうすればよいですか?
上記で述べたように、クロスドメインのHTTP応答を直接取得できます(CORSが有効)が、IFRAMEに読み込まれると、クロスドメインのHTTP応答を読み取ることができないようです。
そして、この質問が十分に解決できないかのように、私にこれらの解決策を除外させます:
easyXDMおよびリモートドメインのエンドポイントを必要とする同様の手法
xML応答の変更(SCRIPT要素を含めるため)、
サーバーサイドプロキシ-ドメインにサーバープロキシがあり、プロキシとして機能する可能性があることを理解しています。
では、これらの2つのソリューションは別として、これを行うことができますか?
multipart/form-data
FORMの送信を模倣するXHR要求(Ajax要求)を偽造することが可能であることがわかります(これは上の画像でファイルをサーバーにアップロードするために使用されます)。
トリックはFormData
コンストラクターを使用することです-詳細については このMozilla Hacksの記事 をお読みください。
これがあなたのやり方です:
// STEP 1
// retrieve a reference to the file
// <input type="file"> elements have a "files" property
var file = input.files[0];
// STEP 2
// create a FormData instance, and append the file to it
var fd = new FormData();
fd.append('file', file);
// STEP 3
// send the FormData instance with the XHR object
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://remote-domain.com/script.pl', true);
xhr.onreadystatechange = responseHandler;
xhr.send(fd);
上記のメソッドは非同期ファイルアップロードを実行します。これは、上記の画像で説明されている通常のファイルアップロードと同等であり、このフォームを送信することで実現されます。
<form action="http://remote-domain.com/script.pl"
enctype="multipart/form-data" method="post">
<input type="file" name="file">
</form>
フォームを送信する代わりに、フォームからのデータを含むクロスドメインXHRリクエストを送信するだけです。 CORSは前者専用です。
他の方法で行う必要がある場合は、postMessageを使用してフレームとネゴシエートします。
また、IFRAMEのコンテンツはXMLドキュメントであるため、IFRAME内にはpostMessageなどを利用できるJavaScriptコードはありません。
それはどのようにあなたを止めますか? HTMLまたはSVG名前空間の下にスクリプト要素を含めます(<script xmlns="http://www.w3.org/1999/xhtml" type="application/ecmascript" src="..."/>
)XMLの任意の場所。
あなたの言い方ではそれはできないと思います。通常、クロスドメインの問題がある場合、JSONpアプローチで解決できますが、これはGETリクエストでのみ機能します。 HTML5を使用すると、GETリクエストでバイナリを送信できる可能性がありますが、それは不確かです。
解決策は、ローカルWebサーバーで要求をプロキシすることにより、リモートWebサービスをローカルで使用可能にすることです。これによりローカルウェブサーバーに追加の負荷がかかるため、実行不可能であると想像できます。ただし、ファイルが小さくて頻度が低い場合は、これで問題ありません。
別の解決策は、ファイルを送信した後でサーバーのポーリングを開始することです。トークンを送信し、通常のJSONpを使用してサーバーのステータスをポーリングできます。この方法では、iframeから読み取る必要はありません。
リモートサーバーで実行されるiframeにページ全体を配置します。これは問題を解決するだけかもしれませんが、XML出力がいくつかのプロセスの最後のステップである場合、それは非常に現実的です。
処理サーバーが別のドメインにあるのには十分な理由があると思いますが、そうでなければ、これらすべての問題は発生しません。おそらく、再考する価値はありますか?