Téléchargement de fichier AJAX avec en-tête personnalisé

Je souhaite envoyer une requête à une URL qui me fournit une boîte de dialogue de téléchargement de fichier. Dans le même temps, le serveur a besoin de certains paramètres dans l'en-tête de requête. Je souhaite donc insérer un en-tête personnalisé dans la requête et obtenir un fichier en réponse. Y a-t-il une façon d'y parvenir?

Merci, Amit

Essayez d'utiliser a élément avec des data-* réglé sur les en-têtes pour la demande, $.ajax() avec l'option des en- headers configurée sur a élément d'en data-headers élément.

À $.ajax() success défini a élément href pour répondre en tant que Blob dans objectURL , download attribut dans le nom du fichier ou du fichier temporaire, appeler .click() sur a élément pour activer la boîte de dialogue "Enregistrer le fichier".

 $(document).ready(function() { $("input[type=button]").click(function() { // set `data-headers` object var el = $("[data-headers]"); el.data("headers")["x-custom-headers"] = $("input[type=text]")[0].value || el.data("headers")["x-custom-headers"]; $.ajax({ url: URL.createObjectURL(new Blob([$("textarea").val()], { type: "text/plain" })), type: "GET", // set `headers` to `a` element `data-headers` object headers: $("[data-headers]").data("headers"), beforeSend: function(jqxhr) { console.log(this.headers); alert("custom headers" + JSON.stringify(this.headers)); }, success: function(data, textStatus, jqxhr) { var file = new Blob([data], { "type": jqxhr.getResponseHeader("Content-Type") }); console.log(data, file); $("textarea, input[type=text]").val(""); $("a") .attr({ "href": URL.createObjectURL(file), "download": file.name || "file-" + $.now() }).on("click", function() { $(this).remove() }) .get(0).click(); }, error: function(jqxhr, textStatus, errorThrown) { console.log(textStatus, errorThrown) } }); }) }) 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> </script> <textarea maxlength="5" placeholder="echo"></textarea> <br> <!-- set `x-custom-header` to `input type="text"` value --> <input type="text" maxlength="5" placeholder="set request header" /> <br /> <input type="button" value="download" /> <!-- set default `x-custom-header` to "123" --> <a data-headers='{"x-custom-headers":"123"}'></a> 

D'après ce que je comprends, vous souhaitez demander un fichier sur le Web qui nécessite un en-tête d'authentification mais ne peut pas être téléchargé avec un lien simple.

Ce que vous devez faire, c'est faire un appel ajax avec l'en-tête d'authentification pour télécharger les données en tant que blob. Ensuite, enregistrez les données du côté client


Les méthodes ajax / get de jQuery ne sont pas compatibles avec responseType = blob

Donc, cet exemple utilise la dernière Fetch API dans Blink et Firefox. Il utilise également FileSaver.js pour sauvegarder un blob généré côté client en fonction des manières de gérer les problèmes de navigation croisée.

 fetch("/", {headers: {"X-mashape-key": "XXXXXX-4-YYYYYY"}}) .then( response => { // we can get the filename if the // response headers contains Content-Disposition var cd = response.headers.get("Content-Disposition"); var name = cd && cd.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)[1]; response.blob().then( blob => window.saveAs(blob, name || "index.html") ) }) 

Il utilise également une nouvelle syntaxe suger qui est disponible dans es6 qui peut être transpilée à es5 avec babel ou traceur

Si vous n'incluez pas un polyfill de récupération et que vous devez prendre en charge les anciens navigateurs – Ensuite, vous devez le faire de l'ancien mode avec XHR

 var xhr = new XMLHttpRequest(); xhr.responseType = 'blob'; xhr.open("get", "/"); xhr.setRequestHeader("X-mashape-key", "XXXXXX-4-YYYYYY"); xhr.send(); xhr.onload = function(){ var cd = xhr.getResponseHeader("Content-Disposition") var name = cd && cd.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)[1]; window.saveAs(xhr.response, name || "index.html") } 

Peut-être que je ne comprends pas votre point de vue.

Ce que je pense est comme ceci:

 //server xxx.php //omit some code echo '<a href="file_path" id="download">file_name</a>'; //browser ajax({ url: 'http://xxxx/xxx.php', success: function(html){ //append to dom and TODO other manipulations $(dom).append(html); $('#download').trigger('click'); $(dom).remove(html); } }) 

Ok, j'ai vérifié une ancienne application que j'avais et voici un exemple. Vous devrez vous adapter mais l'idée est ici. Cette première partie fait partie d'un attribut Request interceptor qui est placé sur le WebMethod . Tout l'intercepteur est assez complexe car il gère plusieurs cas.

 int byteSize = 262144; byte[] data = new byte[byteSize]; if (!String.IsNullOrEmpty(myfileName)) { _context.Response.AddHeader("Content-disposition", "attachment; filename=\"" + myfileName+ "\""); } _context.Response.ContentType = DefaultContentType; _context.Response.Cache.SetCacheability(HttpCacheability.Private); _context.Response.Cache.SetExpires(DateTime.UtcNow.AddHours(1)); _context.Response.Buffer = false; _context.Response.BufferOutput = false; _context.Response.AddHeader("Content-length", myStreamSize.ToString()); try { int counter = 0; int bytesRead = mystream.Read(data, 0, byteSize); while ((long)counter < myStreamSize|| bytesRead > 0) { counter += bytesRead; if (bytesRead < byteSize) { byte[] outBuf = new byte[bytesRead]; Array.Copy(data, outBuf, bytesRead); _context.Response.BinaryWrite(outBuf); } else { _context.Response.BinaryWrite(data); } bytesRead = mystream.Read(data, 0, byteSize); } } finally { mystream.Close(); mystream.Dispose(); } _context.Response.End(); 

C'est la deuxième partie du Javascript du côté client. Nous avons utilisé ExtJS au lieu de jQuery.

 downloadFile: function(url, getArgs) { if( !this.iframe ) { this.iframe = document.createElement("iframe"); this.iframe.className = "x-hidden"; document.body.appendChild(this.iframe); } var args = Ext.urlEncode(getArgs); url = url + (args ? ("?" + args) : ""); this.iframe.src = url; } 

Le clic d'un bouton appellerait cette fonction et lui donnerait l'URL du WebMethod et éventuellement des args supplémentaires à passer. L'idée sur le côté JS est de créer un iFrame caché qui prendrait l'URL et lui demanderait alors de télécharger.

J'espère que ça contribue