47 votes

Est-il possible d'effectuer un téléchargement de fichiers interdomaine asynchrone?

C'est possible! Lire ci-dessous.

Tout d'abord, permettez-moi d'utiliser ce schéma pour expliquer comment asynchrone de téléchargement de fichiers peuvent être obtenus:


Désolé. J'ai fermé un de mes domaines, et l'image est maintenant disparu. C'était vraiment une très belle image bien. C'était avant que j'ai découvert qu'un Débordement de Pile permet de télécharger des images via Imgur.


Comme vous pouvez le voir, le truc est de laisser le HTTP de la réponse de la charge dans un IFRAME masqué élément au lieu de la page elle-même. (Ceci est fait en mettant l' target de la propriété de l'élément de FORMULAIRE lors de l'envoi du FORMULAIRE avec JavaScript.)

Les travaux de cette. Cependant, le problème que je me pose, c'est que le script côté serveur est sur un autre domaine. La FORME de la soumettre est un cross-domain HTTP-request. Maintenant, le script côté serveur de la SCRO a permis qui lui donne ma page web les droits pour lire la réponse-données de HTTP-demande faite à partir de ma page pour ce script, mais qui ne fonctionne que si je reçois le HTTP-réponse via Ajax, ergo, JavaScript.

Cependant, int ce cas, la réponse est dirigée vers l'élément IFRAME. Et une fois la réponse XML terres dans l'IFRAME, son URL sera le script de suppression - par exemple, http://remote-domain.com/script.pl.

Malheureusement, la SCRO ne couvre pas ce cas (du moins je pense) - je ne suis pas capable de lire le contenu de l'IFRAME depuis son URL ne correspond pas à l'URL de la page (domaine différent). J'obtiens cette erreur:

Dangereux JavaScript tentative d'accès à une image avec l'URL hxxp://remote-domain.com/script.pl à partir de l'image avec l'URL hxxp://my-domain.com/outer.html. Les domaines, les protocoles et les ports doivent match.

Et puisque le contenu de l'IFRAME est un document XML, il n'y a pas de code JavaScript à l'intérieur de l'IFRAME qui pourraient utiliser postMessage ou quelque chose.

Donc ma question est: Comment puis-je obtenir le code XML contenu de l'IFRAME?

Comme je l'ai dit plus haut, je suis en mesure de récupérer de la croix-domaine HTTP-réponses directement CORS (activé), mais il semble que je ne suis pas capable de lire de la croix-domaine HTTP-réponses une fois leur chargement, dans une IFRAME.

Et comme si cette question n'est pas insoluble assez, laissez-moi exclure ces solutions:

  1. easyXDM et de techniques similaires qui nécessitent un point final sur le domaine distant,

  2. modifier la réponse XML (inclure un élément de SCRIPT),

  3. côté serveur proxy - je comprendre que je pouvais avoir un script côté serveur sur mon domaine, qui pourraient servir d'un proxy.

Si, en dehors de ces deux solutions, cela peut-il être fait?


Il peut être fait!!

Il s'avère qu'il est possible d'établir un XHR-demande (Ajax demande) qui imite un multipart/form-data soumettre le FORMULAIRE (qui est utilisé dans l'image ci-dessus pour télécharger le fichier sur le serveur).

L'astuce est d'utiliser FormData de constructeur de lire ce Mozilla Hacks article pour plus d'informations.

C'est comment vous le faites:

// 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);

La méthode ci-dessus exécute un fichier asynchrone-uplaod, ce qui est équivalent à la régulière de téléchargement de fichier décrit dans l'image ci-dessus et a réalisé en soumettant ce formulaire:

<form action="http://remote-domain.com/script.pl" 
        enctype="multipart/form-data" method="post">
    <input type="file" name="file">
</form>

Comme un Boss :)

9voto

Eli Grey Points 17553

Il suffit d'envoyer un cross-domain demande XHR avec les données de la forme au lieu de la soumission du formulaire. La SCRO est que pour l'ancien.

Si vous devez le faire dans l'autre sens, de négocier avec le cadre à l'aide de postMessage.

Et puisque le contenu de l'IFRAME est un document XML, il n'y a pas de code JavaScript à l'intérieur de l'IFRAME qui pourraient utiliser postMessage ou quelque chose.

Comment est-ce que vous arrêter? Inclure un élément de script sous le HTML et SVG espace de noms (<script xmlns="http://www.w3.org/1999/xhtml" type="application/ecmascript" src="..."/>) n'importe où dans le fichier XML.

0voto

Halcyon Points 31203

Je pense qu'il ne peut être fait avec la façon dont vous décrivez. Normalement, si vous avez des croix domaine des questions, vous pouvez le résoudre par un JSONp approche, mais qui ne fonctionne que pour les requêtes GET. Avec HTML5, vous pourriez potentiellement envoyer binaire avec la requête GET, mais c'est juste terrible.

  • Une solution serait de rendre la distance webservice disponibles localement par le proxy de la demande sur le serveur web local. Ce sera une charge supplémentaire pour votre serveur web local, donc je peux imaginer que c'est infaisable. Si les fichiers sont petits et peu fréquents, si, cela fera très bien l'affaire.

  • Une autre solution serait de commencer l'interrogation du serveur après que vous ayez envoyé le fichier. Vous pouvez envoyer le long d'un jeton et interroger le statut du serveur à l'aide régulière JSONp. De cette façon, vous n'avez pas besoin de lire à partir de l'iframe.

  • Mettre la totalité de la page dans un iframe qui s'exécute sur le serveur distant. Cela peut seulement déplacer le problème, mais si la sortie XML est la dernière étape d'un processus, il est tout à fait faisable.

Je suis sûr que vous avez de bonnes raisons pour le serveur de traitement pour être dans un domaine différent, mais si ce n'était pas, vous n'auriez pas tous ces problèmes. C'est peut-être la peine de reconsidérer?

-1voto

Mic Points 13418

Si vous le pouvez, renvoyer une page HTML au lieu de XML.
Dans cette page vous pouvez l'utiliser dans un SCRIPT balise de la commande:parent.postMessage

Si vous avez de soutenir les anciens navigateurs(< IE8 principalement), vous pouvez écrire et lire en window.name pour les messages en dessous de 2 mo.

Les deux techniques permet de passer des données de chaîne entre les images de différents domaines.

Une autre technique consiste à utiliser un setInterval qui va appeler à plusieurs reprises le domaine distant à partir de la page parent à l'aide de JSONP pour connaître l'état.

Dans tous les cas, vous aurez besoin d'une coopération à partir de la télécommande de domaine pour obtenir les données.

-1voto

Jiri Points 5589

L'approche suivante est de travailler dans ma configuration (Firefox 3.6):

<!-- hidden target frame -->
<iframe name="load_target" id="load_target" onload="process(this);" src="#" ...>

<!-- get data from iframe after load and process them --> 
<script type="text/javascript">
    function process(iframe) {
       var data = iframe.contentWindow.document.body.innerHTML; 
       // got test data="<xml><a>b</a></xml>"
    }
</script>

Il fonctionne dans Chrome, mais il est nécessaire d'exclure une première onload appel après le chargement de la page parent. Ceci est facilement accompli par la fixation d'un "global" de la variable qui est testé en process().

PLUS

La méthode fonctionne avec un formulaire

<form action="URL" method="post" enctype="multipart/form-data" target="load_target">

qui est soumis à l' URL. Cette URL doit résider sur le même domaine que la page parente page.html. Si les données à partir d'un REMOTE_URL sont à télécharger, puis URL serait un PHP proxy.php sur le propre nom de domaine avec le contenu

<?php echo file_get_contents("REMOTE_URL"); ?>

C'est une approche simple, mais il est probablement exclus par la condition (2) de la question. J'ai ajouté ici pour faire ma réponse complète.

D'autres approches, en considérant les iframes seulement, sont discutés par Mahemoff et Georges Auberger.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X