为什么来自锚元素的http请求不能正常工作?

时间:2018-10-16 13:59:47

标签: javascript

说我有一个HTML页面,该页面可以通过http://example.com/redir.php?id=someID访问。

我希望一些JavaScript在执行时触发http://example.com/?file=hgc56gjyd的下载,并以newFileName的名称提供。

这是我的尝试:

var c = document.createElement("a");
c.href = "?file=hgc56gjyd";
c.download = "newFileName";
c.click();

但是当我执行此操作时,实际的请求是向http://example.com/redir.php?file=hgc56gjyd发送的。请注意添加的'redir.php'。该URL错误,下载的文件为空。但是在这种情况下,更改名称即可。

如果我写出整个URL或使用“ /”或“ ./”(开头):

c.href = "http://example.com/?file=hgc56gjyd"
c.href = "/?file=hgc56gjyd"
c.href = "./?file=hgc56gjyd"

然后download属性不会生效,因此生成的文件不会重命名为newFileName

在获得download的功能的同时,如何触发对正确URI的请求?

这是在Chrome中。

1 个答案:

答案 0 :(得分:1)

这样做:

c.href = "?file=hgc56gjyd";

http://example.com/redir.php?id=someID的文档中,您实际上是在这样做:

c.href = "http://example.com/redir.php?file=hgc56gjyd";
// Note ---------------------^^^^^^^^^

如果您希望将其设置为http://example.com/?file=hgc56gjyd,则不必使用绝对路径-网站内的绝对路径 是Bad Thing™:-)-只需使用前导/或前导./

c.href = "/?file=hgc56gjyd";
// -------^

c.href = "./?file=hgc56gjyd";
// -------^^

如果要转到域根目录,则不管链接所在页面的URL是什么,请使用前者(/);如果您只想要链接所在页面级别的默认URL,则使用后者(./)。在您的示例中,这些是同一回事,但是如果它们位于http://example.com/somethinghere/redir.php?id=someID的页面上,则不会是这样。

实时示例(使用https://stacksnippets.net代替http://example.com的{​​{1}}和js):

redir.php
console.log("Location: " + location);

// Your current code
var c = document.createElement("a");
c.href = "?file=hgc56gjyd";
c.download = "newFileName";
// Notice the `js` on this (which is like your redir.php)
console.log("Your Link:" + c.href);

// The corrected code (#1
var c2 = document.createElement("a");
c2.href = "/?file=hgc56gjyd";
c2.download = "newFileName";
// Notice there's no `js` now
console.log("Fix1:     " + c2.href);

// The corrected code (#2
var c3 = document.createElement("a");
c3.href = "./?file=hgc56gjyd";
c3.download = "newFileName";
// Notice there's no `js` now
console.log("Fix2:     " + c3.href);

在问题和评论中,您已经说过使用.as-console-wrapper { max-height: 100% !important; }“有效”来重命名文件(但不下载它,而是得到一个空文件),但是使用了正确的路径(绝对路径或以上任一解决方案)“无效”,因为它使用了服务器中的名称。但是区别不在于路径本身,而是服务器根据路径发送的内容:"?file=hgc56gjyd"标头的文件名将胜过放置在Content-Disposition属性中的所有内容。实际的下载脚本(位于download)发送它。显然/脚本没有。

解决方案是将文件名方面转移到服务器,并确保返回带有以下标头的文档:

redir.php

例如,如果下载是通过PHP代码处理的,则可以这样做:

Content-Disposition: attachment; filename=newFileName

这样,服务器会告诉浏览器名称。仍然允许浏览器忽略它(但以我的经验,通常使用它)。

如果所有操作均失败(例如,因为您无法更改发送该响应的服务器代码),则还有一个选择:使用BlobURL.createObjectURL(这是{{3 }})。这是使用surprisingly well supported的示例:

<!-- language: lang-php -->

<?php
header("Content-Disposition: attachment; filename=newFileName")

成功使用了// In an event handler... fetch("./?file=hgc56gjyd") .then(response => { if (!response.ok) { throw new Error("HTTP error " + response.status); } return response.blob(); }) .then(blob => { var c = document.createElement("a"); c.href = URL.createObjectURL(blob); c.download = "bar.json"; c.click(); }) .catch(e => { alert(e.message); }); 名称。

如果您不能那样,恐怕您真的很倒霉。 :-|