“强制打开”;另存为……”;在文本链接处打开弹出窗口单击以获取HTML格式的PDF

“强制打开”;另存为……”;在文本链接处打开弹出窗口单击以获取HTML格式的PDF,html,pdf,download,meta-tags,content-disposition,Html,Pdf,Download,Meta Tags,Content Disposition,我有一些大尺寸的PDF目录在我的网站上,我需要链接这些作为下载。当我在谷歌上搜索时,我发现了这样一件事,如下所示。它应该在点击链接时打开“另存为…””弹出窗口 <head> <meta name="content-disposition" content="inline; filename=filename.pdf"> ... ... 但它不工作:/当我链接到一个文件如下,它只是链接到文件,并试图打开该文件 <a href="file

我有一些大尺寸的PDF目录在我的网站上,我需要链接这些作为下载。当我在谷歌上搜索时,我发现了这样一件事,如下所示。它应该在点击链接时打开“另存为…””弹出窗口

 <head>
    <meta name="content-disposition" content="inline; filename=filename.pdf">
    ...

...
但它不工作:/当我链接到一个文件如下,它只是链接到文件,并试图打开该文件

    <a href="filename.pdf" title="Filie Name">File name</a>


更新(根据以下答案):

<a href="/some/good/url/Post-Injection_Post-Surgery_Instructions.pdf" class="force-download" target="_blank">Download PDF</a>
正如我看到的,没有100%可靠的跨浏览器解决方案。最好的方法可能是使用下面列出的web服务之一,并提供下载链接


如果浏览器中有一个知道如何打开PDF文件的插件,它将直接打开。与图像和HTML内容类似


因此,另一种方法是不在响应中发送MIME类型。这样,浏览器将永远不会知道哪个插件应该打开它。因此,它将为您提供一个保存/打开对话框。

通常会出现这种情况,因为某些浏览器设置或插件会像简单的网页一样在同一窗口中直接打开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

将这个小片段保存为服务器上某个地方的PHP文件,您可以使用它在浏览器中下载文件,而不是直接显示。如果要提供PDF以外的文件,请删除或编辑第5行

您可以这样使用它:

将以下链接添加到HTML文件中

<a href="download.php?file=my_pdf_file.pdf">Download the cool PDF.</a>


引用自:

元标记不是实现此结果的可靠方法。一般来说,你甚至不应该这样做——应该由用户/用户代理决定如何处理你提供的内容。如果用户愿意,可以随时强制其浏览器下载文件

如果仍要强制浏览器下载文件,请直接修改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协议的扩展;一些浏览器可能会忽略它。

实现这一点的一个简单方法是,不使用外部下载站点或修改标题等,只需创建一个包含PDF的ZIP文件,并直接链接到ZIP文件。这将始终触发“保存/打开”对话框,人们仍然可以轻松地双击与.zip关联的程序启动的PDF窗口


顺便说一句,这个问题很好,我也在寻找答案,因为大多数嵌入浏览器的PDF插件需要很长时间才能显示任何内容(并且在加载PDF时经常会挂起浏览器)

对于大型PDF文件,浏览器将挂起。 在Mozilla中,菜单工具→ 选择权→ 应用程序,然后在内容类型Adobe Acrobat文档旁边。 在“操作”下拉列表中,选择“始终询问”

这对我不起作用,所以起作用的是:

菜单工具*→ 附加组件→ Adobe Acrobat(用于Firefox的Adobe PDF插件)→ 使残废
现在我可以下载电子书了

我为Firefox找到了一个非常简单的解决方案(仅适用于相对href而非直接href):添加
type=“application/octet stream”


从回答到:


我也遇到了同样的问题,并找到了迄今为止效果很好的解决方案。您将以下代码放入
.htaccess
文件中:

<FilesMatch "\.(?i:pdf)$">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>

ForceType应用程序/八位组流
标题集内容处置附件

它来自。

使用
下载
属性,但要考虑到它只适用于与代码位于同一来源的文件。这意味着用户只能下载来自同一主机的源站点的文件

使用原始文件名下载:


以“some_name”作为文件名下载:


添加
target=“\u blank”
我们将使用一个新选项卡而不是实际的选项卡,并且在某些情况下,它将有助于
download
属性的正确行为

它遵循与同源策略相同的规则。您可以在页面上了解有关此策略的更多信息

您可以在页面上了解有关此下载HTML5属性的更多信息


如果您需要强制下载页面上的单个链接,一种非常简单的方法是在href链接中使用HTML5下载属性

见:

使用此选项,您可以重命名用户将下载的文件,同时强制下载

这是否是一个好的做法一直存在争议,但在我的例子中,我有一个用于PDF文件的嵌入式查看器,查看器不提供下载链接,因此我必须单独提供一个。在这里,我想确保用户不会在web浏览器中打开PDF,这会让人困惑


这将不需要打开“另存为”对话框,但将直接将链接下载到预设的下载目标。当然,如果你正在为其他人创建一个站点,并且需要他们手动将属性写入他们的链接,这可能是一个坏主意,但是如果有办法将属性写入链接,这可能是一个简单的解决方案。

尝试将这一行添加到你的.htaccess文件中


AddType application/octet stream.pdf
在我添加的HTML代码中的文件名之后
?forcedownload=1


这是我触发对话框保存或下载的最简单方法。

只需将以下代码放入
.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);

服务器端解决方案更兼容,直到在所有浏览器中实现“下载”属性

一个Python示例可以是文件存储的自定义HTTP请求处理程序。指向文件存储的链接如下所示:

element.setAttribute( 'download', whatever_string_you_want);
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()
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;
            }
        }
    }
}
<a href="myfile.pdf" download>Click to Download</a>
<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 href="/some/good/url/Post-Injection_Post-Surgery_Instructions.pdf" class="force-download" target="_blank">Download PDF</a>
response.setHeader("Content-Disposition", "attachment;filename=test.jpg");
const fileHandle = await self.showSaveFilePicker({
const blob = fetch("some-url-here").then(data => data.blob());
saveAs(blob, "filename.txt")