我想向URL发送请求,该URL为我提供了文件下载对话框。同时,服务器需要请求标头中的某些参数。我想在请求中插入自定义标头并获取响应文件。有什么方法可以实现这个目标吗?
答案 0 :(得分:8)
尝试使用a
元素并将data-*
设置为请求标头,$.ajax()
并将headers
选项设置为a
元素data-headers
对象。
在$.ajax()
success
设置a
元素href
,以Blob
为objectURL
,download
属性为{{} 1}}或临时文件名,在file.name
元素上调用.click()
以激活"保存文件"对话。
a

$(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)
}
});
})
})

答案 1 :(得分:6)
根据我的理解,您想要从网络上请求需要身份验证标题的文件,但无法通过简单的链接下载。
您需要做的是使用身份验证标头进行ajax调用,以将数据下载为blob。然后从客户端保存数据
jQuery的ajax / get方法不支持responseType = blob
因此,此示例使用Blink和Firefox中的最新Fetch API。它还使用FileSaver.js来保存客户端生成的blob以及处理跨浏览器问题的方式。
<style name="CustomDialogTheme" parent="@android:style/Theme.Holo.Light.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
<item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
</style>
它还使用es6中提供的一些新的suger语法,可以使用babel或traceur转换为es5
如果您不包含fetch polyfill并且需要支持旧版浏览器 - 那么您需要使用旧时尚方式使用XHR
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")
)
})
答案 2 :(得分:-1)
也许我不明白你的观点。
我认为是这样的:
//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);
}
})
答案 3 :(得分:-1)
好的,我查了一个旧的应用程序,这里有一个样本。你需要适应,但这个想法就在这里。
第一部分是放置在WebMethod
上的Request拦截器属性的一部分。整个拦截器非常复杂,因为它管理了几个案例。
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();
这是客户端Javascript的第二部分。我们使用ExtJS而不是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;
}
点击按钮会调用此函数并为其提供WebMethod的URL,并最终传递额外的args。 JS方面的想法是创建一个隐藏的iFrame,它将获取URL,然后提示用户下载。
我希望它有所帮助