【问题标题】:Request a file with a custom header请求带有自定义标头的文件
【发布时间】:2012-05-17 23:46:09
【问题描述】:

我有一个不寻常的要求。本质上,我需要一种方法,以便当用户单击链接或按钮时,他们将收到 PDF。这里棘手的部分是服务器不会处理请求根本,除非随它一起发送自定义标头(否则它认为该人已注销并将其发送到登录屏幕)。 p>

目前标题的工作方式无法更改,因此请不要纠缠于此;它将在未来发生变化,并且是我无法控制的内部应用程序。

我探索过的选项:

  • 使用 iframe 或简单地打开带有某种路径的新窗口,该路径将返回 PDF。这不起作用,因为我无法为 PDF 指定所需的标头,并且会在到达 PDF 本身之前被重定向。
  • 无法使用表单并提交请求,因为我不能 向表单添加任何自定义标题(只有 XHR 和插件可以,AFAIK)。
  • 使用 XHR 无法工作,因为它可以添加标题和 检索文件,无法将其保存在客户端。

看来我目前唯一的选择基本上是:

  • 使用某种插件(例如 Flash 或 Silverlight)来请求文件。
  • 比预期更早地强制要求更改,以便不再需要标头。

这里有什么我遗漏的吗?我希望有人可以验证我的发现或指出我错过的东西,因为据我所知,我在这里真的无能为力。

编辑:这似乎很恰当,并证实了我的想法:XMLHttpRequest to open PDF in browser

【问题讨论】:

  • 在应用程序和脚本之间添加某种隧道怎么样?隧道可以查询应用程序并接收文件,然后在将文件刷新给用户之前设置适当的标头,从而实际触发下载。我不知道这是否适用于您的系统,具体取决于安全性。
  • 隧道不是一个坏主意,虽然我不确定我们可以在这里实现它。唔。谢谢,我会调查的。
  • 如果您可以不支持 IE stackoverflow.com/q/9620497 另请参阅 stackoverflow.com/q/6165266html5rocks.com/en/tutorials/file/xhr2
  • 实际上,我们只支持 Moz 和 Webkit,所以 blob url 可能会很好地工作!我会戳一下。谢谢!
  • @LasseChristiansen-sw_lasse 唯一在技术上看起来可行的真正解决方案是使用 blob URL。因此,本质上是从服务中获取 PDF blob 并传递标头,然后将 PDF 嵌入到 blob URL 中,此时如果用户单击它,他们将获得 PDF。 Esailija 与我的最终解决方案非常相似,我只是从未标记它有答案。

标签: javascript html forms http header


【解决方案1】:

经过测试可以在 chrome 中工作:

function toBinaryString(data) {
    var ret = [];
    var len = data.length;
    var byte;
    for (var i = 0; i < len; i++) { 
        byte=( data.charCodeAt(i) & 0xFF )>>> 0;
        ret.push( String.fromCharCode(byte) );
    }

    return ret.join('');
}


var xhr = new XMLHttpRequest;

xhr.open( "GET", "/test.pdf" ); //I had test.pdf this on my local server


xhr.addEventListener( "load", function(){
    var data = toBinaryString(this.responseText);
    data = "data:application/pdf;base64,"+btoa(data);
    document.location = data;
}, false);

xhr.setRequestHeader("magic", "header" );
xhr.overrideMimeType( "application/octet-stream; charset=x-user-defined;" );
xhr.send(null);

您可以将 application/pdf 更改为 application/octet-stream 以获得下载提示。但也很容易从 chrome 的阅读器下载。

在 Firefox 中没有任何反应,我想这是因为我没有安装插件来处理 application/pdf。更改为 application/octet-stream 将提示 dl。

对于 IE,我想你需要某种 VBScript/ActiveX 黑客技术

如果文件很大,使用 data uri 可能会导致浏览器崩溃,在这种情况下,您可以使用 BlobBuilder 和 Object URL。

【讨论】:

  • 是否可以为下载设置自定义文件名?
【解决方案2】:

不要链接到 .PDF 文件,而是执行类似

的操作
<a href="pdf_server.php?file=pdffilename">Download my eBook</a>

它输出一个自定义标题,打开 PDF(二进制安全)并将数据打印到用户的浏览器,然后他们可以选择保存 PDF,尽管他们的浏览器设置。 pdf_server.php 应该如下所示:

header("Content-Type: application/octet-stream");

$file = $_GET["file"] .".pdf";
header("Content-Disposition: attachment; filename=" . urlencode($file));   
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");            
header("Content-Length: " . filesize($file));
flush(); // this doesn't really matter.
$fp = fopen($file, "r");
while (!feof($fp))
{
    echo fread($fp, 65536);
    flush(); // this is essential for large downloads
} 
fclose($fp);

编辑:从浏览器内部(客户端)向请求添加标头的唯一方法是使用XmlHttpRequest setRequestHeader 方法。

xhr.setRequestHeader('custom-header', 'value');

【讨论】:

  • 这基本上是我的第一个想法,但是,必须在客户端添加标头,因为没有所述标头,服务器根本不会处理任何内容。因此,除非我在客户端和当前服务器架构之间使用某些东西,否则不会执行任何服务器端。
  • 您不必在客户端添加标头。只要 php 文件中的标头之前绝对没有文本,这应该可以工作。
  • 我想你误解了我的要求。生成 PDF 的服务器需要与所有请求一起发送自定义标头。如果未发送标头,则假定用户已注销,不运行服务器端代码,并且此人被重定向到登录屏幕。我正在尝试确认我的发现,因为我相信我在证明一个好的解决方案方面非常有限。
  • 向请求客户端添加标头的唯一方法是使用 XmlHttpRequest setRequestHeader 方法。
猜你喜欢
  • 2016-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-24
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多