强制打开“另存为...”弹出窗口在文本链接处打开单击以获取 HTML 中的 PDF
Posted
技术标签:
【中文标题】强制打开“另存为...”弹出窗口在文本链接处打开单击以获取 HTML 中的 PDF【英文标题】:Force to open "Save As..." popup open at text link click for PDF in HTML 【发布时间】:2011-04-17 16:20:09 【问题描述】:我的网站上有一些大尺寸的 PDF 目录,我需要将它们链接为下载。当我用谷歌搜索时,我发现下面提到了这样的事情。它应该会在点击链接时打开“Save As...”弹出窗口...
<head>
<meta name="content-disposition" content="inline; filename=filename.pdf">
...
但它不起作用:/当我链接到如下文件时,它只是链接到文件并试图打开文件。
<a href="filename.pdf" title="Filie Name">File name</a>
更新(根据下面的答案):
据我所知,没有 100% 可靠的跨浏览器解决方案。可能最好的方法是使用下面列出的网络服务之一,并提供下载链接...
http://box.net/ http://droplr.com/ http://getcloudapp.com/【问题讨论】:
不要为 pdf 文件提供 mimetype。 我尝试了您的更新解决方案,artmania - 但发生了我在 Safari 中遇到的同样问题。我在浏览器窗口中看到了类似于 PDF 的内容,只有当我点击底部的“预览”或“下载”选项卡时,我才能获得我迫切需要的搜索功能。 无点击:***.com/questions/2598658/… 类似但文件类型较少:***.com/questions/1465573/… 【参考方案1】:来自Force a browser to save file as after clicking link的回复:
<a href="path/to/file" download>Click here to download</a>
【讨论】:
在发表此评论时,download
属性仅限于 Chrome、Firefox 和 Opera。即使是最新版本的 IE 和 Safari 也不支持它。如需未来支持:请查看caniuse.com/#feat=download!
Netbeans 错误检查抱怨它,但它似乎工作正常。您可以为新文件指定一个初步名称,如下所示:download="myFile.txt"
在撰写此评论时,这在 Edge 中有效,并且似乎是阻止在 Edge 在 PDF 查看器中非常糟糕的尝试中打开超链接 PDF 的唯一方法。
在发表此评论时,我已经在 Chrome、Opera、Edge、Mozilla 上对其进行了测试。都是最新的。正在开发除 Mozilla 之外的所有内容。
这仅适用于同源链接,如caniuse.com/#feat=download 所述。如果您的链接是跨域的,您唯一的选择(目前)是强制响应类型为“application/octet-stream”,正如许多答案所暗示的那样。如果你无权访问服务器,那么你可以尝试代理它并手动设置响应头。【参考方案2】:
使用download
属性,但请注意它仅适用于与您的代码同源的文件。这意味着用户只能下载来自源站、同一主机的文件。
使用原始文件名下载:
<a href="file link" download target="_blank">Click here to download</a>
使用 'some_name' 作为文件名下载:
<a href="file link" download="some_name" target="_blank">Click here to download</a>
添加target="_blank"
,我们将使用一个新选项卡而不是实际选项卡,这也有助于download
属性在某些情况下的正确行为。
它遵循与同源策略相同的规则。您可以在MDN Web Doc same-origin policy 页面上了解有关此政策的更多信息
您可以在MDN Web Doc anchor's attributes 页面上了解有关此下载 html5 属性的更多信息。
【讨论】:
它与当前的最佳答案完全相同,来自 2013 年的 Ayush Gupta。target="_blank"
可能使它对不支持的浏览器更有用,不过(PDF 然后在新窗口中打开/tab,而不是覆盖当前页面)。
对我来说,target="_blank"
是必要的,因为 download
只是未能正确触发下载(Chrome)
如果你在download
属性中给出一个字符串,它将被用作文件名。我一直在用户脚本中使用它。
如果我错了请纠正我,但下载不是“另存为”对话框。 Doenload 和 target _blank 只是在新选项卡中打开文件。
仅适用于同源!【参考方案3】:
元标记不是实现此结果的可靠方法。通常你甚至不应该这样做——应该由用户/用户代理来决定如何处理你提供的内容。用户可以随时强制他们的浏览器下载文件。
如果还想强制浏览器下载文件,直接修改HTTP头即可。这是一个 php 代码示例:
$path = "path/to/file.pdf";
$filename = "file.pdf";
header('Content-Transfer-Encoding: binary'); // For Gecko browsers mainly
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($path)) . ' GMT');
header('Accept-Ranges: bytes'); // Allow support for download resume
header('Content-Length: ' . filesize($path)); // File size
header('Content-Encoding: none');
header('Content-Type: application/pdf'); // Change the mime type if the file is not PDF
header('Content-Disposition: attachment; filename=' . $filename); // Make the browser display the Save As dialog
readfile($path); // This is necessary in order to get it to actually download the file, otherwise it will be 0Kb
请注意,这只是对 HTTP 协议的扩展;无论如何,一些浏览器可能会忽略它。
【讨论】:
在实践中,我相信这已被广泛实施。 这是最好的解决方案,无忧且有效。您可以使用此方法直接下载任何文件类型。 +1 HTTP 中不存在内容传输编码。内容编码:无用。 在你的回答中做一个注释,如果文件来自外部服务器/域,那么这个答案可能不是解决方案...... 我想补充一点,当文件变大(在我的情况下为 >80 MB)时,某些服务器上的此代码或类似代码会失败。使用ob_end_flush()
也没有帮助。【参考方案4】:
我遇到了同样的问题,并找到了一个迄今为止效果很好的解决方案。您将以下代码放入您的 .htaccess
文件中:
<FilesMatch "\.(?i:pdf)$">
ForceType application/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
它来自Force a File to Download Instead of Showing Up in the Browser。
【讨论】:
这很好用,因为我有一个特定的文档目录可供下载。我省略了 ForceType,只是为了让类型保持原样。我也不需要不区分大小写;我的似乎已经不区分大小写了。我添加了一些额外的类型,包括用于旧/新 Office 扩展的 optional-x:<FilesMatch "\.(pdf|xlsx?|docx?)$">
这很好用,即使在 OSX Safari 中也是如此,因为其他答案(包括接受的答案,正如一位评论者指出的那样)仅限于支持给定 HTML 功能的某些浏览器。这个对我来说似乎更理想,因为它可以全面工作,尽管它确实需要对服务器配置文件进行更高级别的访问。
你也可以把它放在你的 apache.conf 文件中,我不使用 .htaccess,因为它需要更多资源。
Windows 托管的网站如何实现这一点,因为它们无法读取 htaccess 文件?【参考方案5】:
我为 Firefox 找到了一个非常简单的解决方案(仅适用于相对而不是直接 href):添加 type="application/octet-stream"
:
<a href="./file.pdf" id='example' type="application/octet-stream">Example</a>
【讨论】:
@Martin Chrome 在 Chrome OS 上和 Firefox 在 Linux 上。事实证明,该文件需要在本地才能正常工作。我的 href 是云存储的 url。【参考方案6】:一般会出现这种情况,因为有些浏览器设置或插件直接在同一个窗口中打开PDF,就像一个简单的网页一样。
以下内容可能会对您有所帮助。几年前我用 PHP 做过。但目前我不在那个平台上工作。
<?php
if (isset($_GET['file']))
$file = $_GET['file'];
if (file_exists($file) && is_readable($file) && preg_match('/\.pdf$/',$file))
header('Content-type: application/pdf');
header("Content-Disposition: attachment; filename=\"$file\"");
readfile($file);
else
header("HTTP/1.0 404 Not Found");
echo "<h1>Error 404: File Not Found: <br /><em>$file</em></h1>";
?>
将以上内容另存为download.php。
将这个小sn-p 保存为服务器上某处的PHP 文件,您可以使用它在浏览器中下载文件,而不是直接显示。如果您想提供 PDF 以外的文件,请删除或编辑第 5 行。
你可以这样使用它:
将以下链接添加到您的 HTML 文件中。
<a href="download.php?file=my_pdf_file.pdf">Download the cool PDF.</a>
参考来自:This blog
【讨论】:
这似乎是一种很好的方式,可以将服务器上的每个文件提供给任何关注的人。以download.php?file=database_password_file.php
为例。【参考方案7】:
尝试将此行添加到您的 .htaccess 文件中。
AddType application/octet-stream .pdf
我希望它能工作,因为它独立于浏览器。
【讨论】:
我很想知道为什么这被否决了 - 这是最简单的方法之一:css-tricks.com/snippets/htaccess/… 人们尝试在免费托管网站上修改服务器的核心功能,然后因为无法使其正常工作而投反对票。每个其他解决方案都会有一些警告,因为它是一个“黑客”来取代它。 我不赞成它,因为它是解决问题的错误方法。搞乱资源类型是个坏主意。 @NathanHornby - 我没有投反对票,但这不适用于任何 Windows 托管网站,因为它们不使用 .htaccess。 我没有投反对票,但这个解决方案会盲目地影响该后缀的所有文件。这是不分青红皂白的,因此并不适用于所有情况。【参考方案8】:我刚用过这个,不知道它是否适用于所有浏览器。
它适用于 Firefox:
<a href="myfile.pdf" download>Click to Download</a>
【讨论】:
在an earlier answer 中建议并提供更多背景信息。【参考方案9】:真正实现此目的的简单方法是无需使用外部下载站点或修改标题等,只需创建一个包含 PDF 的 ZIP 文件并直接链接到该 ZIP 文件。这将始终触发“保存/打开”对话框,并且人们仍然可以轻松双击启动与 .zip 关联的程序的 PDF 窗口。
顺便说一句,这个问题很好,我也在寻找答案,因为大多数嵌入浏览器的 PDF 插件需要很长时间才能显示任何内容(并且在加载 PDF 时通常会挂起浏览器)。
【讨论】:
糟糕的可用性。许多最终用户不知道如何处理 zip 文件。 有时简单的解决方案是最好的解决方案! 不是一个好的解决方案。我对 Firefox 和一个 ZIP 文件有这个问题。我该怎么办?压缩文件?在这种情况下,修改 HTTP 标头可能是一种解决方案,但我无权访问。【参考方案10】:只需将以下代码放入您的 .htaccess
文件中:
AddType application/octet-stream .csv
AddType application/octet-stream .xls
AddType application/octet-stream .doc
AddType application/octet-stream .avi
AddType application/octet-stream .mpg
AddType application/octet-stream .mov
AddType application/octet-stream .pdf
或者你也可以通过 javascript 来做恶作剧
element.setAttribute( 'download', whatever_string_you_want);
【讨论】:
这不是假定网络服务器是Apache吗?【参考方案11】:服务器端解决方案更兼容,直到所有浏览器都实现“下载”属性。
一个 Python 示例可以是文件存储的自定义 HTTP 请求处理程序。指向文件存储的链接生成如下:
http://www.myfilestore.com/filestore/13/130787e71/download_as/desiredName.pdf
代码如下:
class HTTPFilestoreHandler(SimpleHTTPRequestHandler):
def __init__(self, fs_path, *args):
self.fs_path = fs_path # Filestore path
SimpleHTTPRequestHandler.__init__(self, *args)
def send_head(self):
# Overwrite SimpleHTTPRequestHandler.send_head to force download name
path = self.path
get_index = (path == '/')
self.log_message("path: %s" % path)
if '/download_as/' in path:
p_parts = path.split('/download_as/')
assert len(p_parts) == 2, 'Bad download link:' + path
path, download_as = p_parts
path = self.translate_path(path )
f = None
if os.path.isdir(path):
if not self.path.endswith('/'):
# Redirect browser - doing basically what Apache does
self.send_response(301)
self.send_header("Location", self.path + "/")
self.end_headers()
return None
else:
return self.list_directory(path)
ctype = self.guess_type(path)
try:
f = open(path, 'rb')
except IOError:
self.send_error(404, "File not found")
return None
self.send_response(200)
self.send_header("Content-type", ctype)
fs = os.fstat(f.fileno())
self.send_header("Expires", '0')
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
self.send_header("Cache-Control", 'must-revalidate, post-check=0, pre-check=0')
self.send_header("Content-Transfer-Encoding", 'binary')
if download_as:
self.send_header("Content-Disposition", 'attachment; filename="%s"' % download_as)
self.send_header("Content-Length", str(fs[6]))
self.send_header("Connection", 'close')
self.end_headers()
return f
class HTTPFilestoreServer:
def __init__(self, fs_path, server_address):
def handler(*args):
newHandler = HTTPFilestoreHandler(fs_path, *args)
newHandler.protocol_version = "HTTP/1.0"
self.server = BaseHTTPServer.HTTPServer(server_address, handler)
def serve_forever(self, *args):
self.server.serve_forever(*args)
def start_server(fs_path, ip_address, port):
server_address = (ip_address, port)
httpd = HTTPFilestoreServer(fs_path, server_address)
sa = httpd.server.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()
【讨论】:
【参考方案12】:这是旧帖子,但这是我在 JavaScript 中使用 jQuery 库的解决方案。
<script>
(function($)
var download = [];
$('a.force-download, .force-download a').each(function()
// Collect info
var $this = $(this),
$href = $this.attr('href'),
$split = $href.split('/'),
$name = document.title.replace(/[\W_]/gi, '-').replace(/-2,/g, '-'); // get title and clean it for the URL
// Get filename from URL
if($split[($split.length-1)])
$tmp = $split[($split.length-1)];
$tmp = $tmp.split('.');
$name = $tmp[0].replace(/[\W_]/gi, '-').replace(/-2,/g, '-');
// If name already exists, put timestamp there
if($.inArray($name, download) > -1)
$name = $name + '-' + Date.now().replace(/[\W]/gi, '-');
$(this).attr("download", $name);
download.push($name);
);
(jQuery || window.jQuery))
</script>
您只需要在您的<a>
标签中使用force-download
类,它就会自动强制下载。您也可以将其添加到父 div
并获取其中的所有链接。
示例:
<a href="/some/good/url/Post-Injection_Post-Surgery_Instructions.pdf" class="force-download" target="_blank">Download PDF</a>
这非常适合 WordPress 和任何其他系统或自定义网站。
【讨论】:
【参考方案13】:如果您需要强制下载页面上的单个链接,一个非常简单的方法是使用 href-link 中的 HTML5 下载属性。
见:http://davidwalsh.name/download-attribute
您可以重命名用户将下载的文件,同时强制下载。
这是否是一种好的做法一直存在争议,但在我的情况下,我有一个 PDF 文件的嵌入式查看器,并且查看器不提供下载链接,所以我必须单独提供一个。在这里,我想确保用户不会在 Web 浏览器中打开 PDF,这会造成混淆。
这不需要打开另存为对话框,但会将链接直接下载到预设的下载目标。当然,如果您正在为其他人创建网站,并且需要他们手动将属性写入其链接可能是个坏主意,但如果有办法将属性放入链接中,这可能是一个轻松的解决方案。
【讨论】:
【参考方案14】:添加响应头 Content-Disposition:attachment;后跟文件名。删除 Meta Content-Disposition;Inline;这将在同一窗口中打开文档
在java中设置为
response.setHeader("Content-Disposition", "attachment;filename=test.jpg");
【讨论】:
【参考方案15】:在 HTML 代码中的文件名后添加?forcedownload=1
这是我触发保存或下载对话框的最简单方法。
【讨论】:
【参考方案16】:如果您在浏览器中有一个知道如何打开 PDF 文件的插件,它将直接打开。就像图像和 HTML 内容一样。
因此,另一种方法是不在响应中发送您的 MIME 类型。这样,浏览器将永远不知道应该打开哪个插件。因此它会给你一个保存/打开对话框。
【讨论】:
这很难实现,因为它是发送 mime 类型的服务器,并且当直接链接到 PDF 文件时,您无法更改标题。【参考方案17】:我刚刚遇到了一个非常相似的问题,即我需要在 ZIP 文件中创建指向文件的下载链接。
我首先尝试创建一个临时文件,然后提供了一个指向临时文件的链接,但我发现有些浏览器只会显示内容(CSV Excel 文件)而不是提供下载。最终我通过使用 servlet 找到了解决方案。它适用于 Tomcat 和 GlassFish,我在 Internet Explorer 10 和 Chrome 上试用过。
servlet 将 ZIP 文件的完整路径名和应下载的 zip 文件名作为输入。
在我的 JSP 文件中,我有一个表格,其中显示了 zip 中的所有文件,其中的链接显示:onclick='download?zip=<%=zip%>&csv=<%=csv%>'
servlet 代码在 download.java 中:
package myServlet;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.zip.*;
import java.util.*;
// Extend HttpServlet class
public class download extends HttpServlet
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
PrintWriter out = response.getWriter(); // now we can write to the client
String filename = request.getParameter("csv");
String zipfile = request.getParameter("zip");
String aLine = "";
response.setContentType("application/x-download");
response.setHeader( "Content-Disposition", "attachment; filename=" + filename); // Force 'save-as'
ZipFile zip = new ZipFile(zipfile);
for (Enumeration e = zip.entries(); e.hasMoreElements();)
ZipEntry entry = (ZipEntry) e.nextElement();
if(entry.toString().equals(filename))
InputStream is = zip.getInputStream(entry);
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"), 65536);
while ((aLine = br.readLine()) != null)
out.println(aLine);
is.close();
break;
要在 Tomcat 上编译,您需要包含 tomcat\lib\servlet-api.jar 或 GlassFish 的类路径:glassfish\lib\j2ee.jar
但是任何一个都可以同时工作。您还需要在web.xml
中设置您的servlet。
【讨论】:
【参考方案18】:Chrome 91 有一个新的变化,它支持 chrome 86-90 和 91+。 下面的语法将使它发生。
const fileHandle = await self.showSaveFilePicker(
suggestedName: 'Untitled Text.txt',
types: [
description: 'Text documents',
accept:
'text/plain': ['.txt'],
,
],
);
在这里阅读更多:
https://developer.chrome.com/blog/new-in-chrome-91/
**另一种解决方案,您可以将其制作为 blob,然后使用 saveAs **
const blob = fetch("some-url-here").then(data => data.blob());
saveAs(blob, "filename.txt")
【讨论】:
【参考方案19】:对于大型 PDF 文件,浏览器会挂起。 在 Mozilla 中,菜单 Tools → Options → Applications,然后在内容类型 Adobe Acrobat 文档旁边。 在操作下拉列表中,选择总是询问。
这对我不起作用,所以起作用的是:
菜单工具* → 附加组件 → Adobe Acrobat(用于 Firefox 的 Adobe PDF 插件)→ 禁用。 现在我可以下载电子书了!
【讨论】:
你读过这个问题吗?这不是跨浏览器的答案 @mark 这也是用户提示强制下载 PDF 的说明,而不是网站所有者。以上是关于强制打开“另存为...”弹出窗口在文本链接处打开单击以获取 HTML 中的 PDF的主要内容,如果未能解决你的问题,请参考以下文章