Force to open “Save As…” popup open at text link click for PDF in HTML

后端 未结 18 1167
無奈伤痛
無奈伤痛 2020-11-22 10:28

I have some big size PDF catalogs at my website, and I need to link these as download. When I googled, I found such a thing noted below. It should open the \"Save As

相关标签:
18条回答
  • 2020-11-22 11:05

    A very easy way to do this, if you need to force download for a single link on your page, is to use the HTML5 download-attribute in the href-link.

    See: http://davidwalsh.name/download-attribute

    with this you can rename the file that the user will download and at the same time it forces the download.

    There has been a debate whether this is good practice or not, but in my case I have an embedded viewer for a PDF file and the viewer does not offer a download link, so i have to provide one separately. Here I want to make sure the user does not get the PDF opened in the web browser, which would be confusing.

    This won't necessary open the save as-dialog, but will download the link straight to the preset download destination. And of course if you are doing a site for someone else, and need them to write in manually attributes to their links is probably a bad idea, but if there is way to get the attribute into the links, this can be a light solution.

    0 讨论(0)
  • 2020-11-22 11:05

    A server-side solution is more compatible, until the "download" attribute is implemented in all the browsers.

    One Python example could be a custom HTTP request handler for a filestore. The links that point to the filestore are generated like this:

    http://www.myfilestore.com/filestore/13/130787e71/download_as/desiredName.pdf

    Here is the code:

    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()
    
    0 讨论(0)
  • 2020-11-22 11:09

    If you have a plugin within the browser which knows how to open a PDF file it will open directly. Like in case of images and HTML content.

    So the alternative approach is not to send your MIME type in the response. In this way the browser will never know which plugin should open it. Hence it will give you a Save/Open dialog box.

    0 讨论(0)
  • 2020-11-22 11:13

    A really simple way to achieve this, without using external download sites or modifying headers etc. is to simply create a ZIP file with the PDF inside and link directly to the ZIP file. This will ALWAYS trigger the Save/Open dialog, and it's still easy for people to double-click the PDF windows the program associated with .zip is launched.

    BTW great question, I was looking for an answer as well, since most browser-embedded PDF plugins take sooo long to display anything (and will often hang the browser whilst the PDF is loading).

    0 讨论(0)
  • 2020-11-22 11:13

    Add a response header Content-Disposition:attachment; followed by the file name. Remove the Meta Content-Disposition;Inline; which will open the document in the same window

    In java it is set as

    response.setHeader("Content-Disposition", "attachment;filename=test.jpg");
    
    0 讨论(0)
  • 2020-11-22 11:15

    I just used this, but I don't know if it works across all browsers.

    It works in Firefox:

    <a href="myfile.pdf" download>Click to Download</a>
    
    0 讨论(0)
提交回复
热议问题