HTMLのPDFのテキストリンククリックで[名前を付けて保存]ポップアップを強制的に開く


173

自分のウェブサイトに大きなサイズのPDFカタログがいくつかあり、ダウンロードとしてリンクする必要があります。ググると、以下のようなものが見つかりました。これは、「開く必要があります名前を付けて保存...」リンクをクリックでポップアップを...

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

しかし、それは動作しません:/以下のようにファイルにリンクすると、ファイルにリンクするだけでファイルを開こうとします。

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

更新(以下の回答による):

私が見るように、これのための100%信頼できるクロスブラウザソリューションはありません。おそらく最善の方法は、以下にリストされているWebサービスの1つを使用して、ダウンロードリンクを提供することです...


1
PDFファイルのMIMEタイプを提供しません。
bhups

更新されたソリューションartmaniaを試しましたが、Safariで同じ問題が発生しました。ブラウザウィンドウでPDFのように表示されます。下部にある[プレビュー]または[ダウンロード]タブをクリックしたときにのみ、必要な検索機能が表示されます。
ヒースウォーラー2010


回答:


267

リンクをクリックした後のようにブラウザにファイルを保存するようにという回答から:

<a href="path/to/file" download>Click here to download</a>

17
このコメントの時点では、download属性はChrome、Firefox、Operaに限定されています。IEとSafariの最近のバージョンでもサポートしていません。今後のサポートについては、caniuse.com /#feat = downloadを確認してください
シグモラル2014

Netbeansのエラーチェックはそれについて不平を言っていますが、問題なく動作しているようです。次のように新しいファイルの仮の名前を指定できます。download= "myFile.txt"
Yster

1
これは、このコメントを書いている時点でEdgeで機能し、EdgeのPDFビューアでの非常に貧弱な試みでハイパーリンクPDFが開かないようにする唯一の方法のようです。

このコメントの時点で、Chrome、Opera、Edge、Mozillaでテストしました。すべて最新。Mozilla以外のすべてに取り組んでいます。
SI

7
caniuse.com/#feat=downloadに記載されているように、これは同じ生成元のリンクでのみ機能します。リンクがクロスオリジンである場合、多くの回答が示唆するように、(現時点では)唯一のオプションは、応答タイプを「application / octet-stream」に強制することです。サーバーにアクセスできない場合は、サーバーにプロキシして、応答ヘッダーを手動で設定することができます。
ジャン

80
<a href="file link" download target="_blank">Click here to download</a>

FirefoxとChromeで動作します。


2
ただし、2013年のAyush Guptaからの現在のトップアンサーとまったく同じです。ただし、target="_blank"サポートされていないブラウザーでは、PDFを少し使いやすくすることができます(PDFは、現在のページを上書きするのではなく、新しいウィンドウ/タブで開きます)。
シグモラル2014

3
私にとっては、ダウンロードを正しくトリガーできなかったためtarget="_blank"に必要downloadでした(Chrome)
casraf

2
download属性に文字列を指定すると、ファイル名として使用されます。私はいつもそれをユーザースクリプトで使っています。
ウィークネスパース

34

メタタグは、この結果を実現するための信頼できる方法ではありません。通常、これを行うべきではありません。提供するコンテンツの処理方法は、ユーザーまたはユーザーエージェントに委ねる必要があります。ユーザーは、必要に応じていつでもブラウザにファイルをダウンロードさせることができます。

それでもブラウザにファイルをダウンロードさせたい場合は、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プロトコルの拡張であることに注意してください。一部のブラウザは、とにかくそれを無視するかもしれません。


4
実際には、これは広く実装されていると思います。
Matthew Wilson

これが最善の解決策であり、手間がかからず機能します。この方法を使用して、任意のファイルタイプを直接ダウンロードできます。+1
casraf

3
Content-Transfer-EncodingはHTTPには存在しません。Content-Encoding:どれも役に立たない。
Julian Reschke 2012

IFファイルが外部サーバー/ドメインからのものであることを回答でメモしてください。この回答は解決策ではない可能性があります...
T.Todua

ファイルが大きくなると(特定のサーバーでは80 MBを超える)、特定のサーバーでこのコードまたは同様のコードが失敗したことを付け加えておきます。使用ob_end_flush()しても効果がありませんでした。
Hendrik

22

私はこれと同じ問題を抱えており、これまでのところうまくいった解決策を見つけました。次のコードを.htaccessファイルに入れます。

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

これは、ブラウザに表示されるのではなく、ファイルを強制的にダウンロードすることから来ました


4
ダウンロード用の特定のドキュメントディレクトリがあったので、これはうまくいきました。型をそのままにするために、ForceTypeを省略しました。また、大文字と小文字を区別する必要もありませんでした。私はすでに大文字と小文字を区別しないようです。:私は古い/新しいOfficeの拡張のためのオプションの-Xを含むカップルの余分なタイプを追加<FilesMatch "\.(pdf|xlsx?|docx?)$">
goodeye

これは、OSX Safariでもうまく機能しました。他の回答(承認された回答を含め、コメント投稿者が指摘したもの)は、特定のHTML機能をサポートする特定のブラウザーに限定されています。これは全体的に機能するため、私にとってはより理想的ですが、サーバー構成ファイルへのより高いレベルのアクセスが必要です。
bwright

それをapache.confファイルに追加することもできますが、.htaccessは使用しません。リソースが多く必要になるためです。
マイケルフィーバー

WindowsがホストするWebサイトは、htaccessファイルを読み取ることができないため、これをどのように実装しますか?
PoloHoleSet

9

私はFirefoxの非常にシンプルなソリューションを見つけました(直接のhrefではなく、相対でのみ機能します):add type="application/octet-stream"

<a href="./file.pdf" id='example' type="application/octet-stream">Example</a>

1
@Martin Chrome(Chrome OS)およびFirefox(Linux)。ファイルが機能するためには、ファイルがローカルである必要があることがわかります。私のhrefはクラウドストレージへのURLでした。
ttfreeman

7

この行を.htaccessファイルに追加してみてください。

AddType application/octet-stream .pdf

ブラウザに依存しないのでうまくいくと思います。


なぜこれが反対票を投じられたのか知りたいです。これは最も単純な方法の1つであり、機能します。css
Nathan Hornby

人々は、無料のホスティングサイトでサーバーのコア機能を変更しようとし、それを機能させることができないために反対票を投じます。これを置き換える「ハック」であるため、他のすべてのソリューションには警告があります。
放棄されたカート

それは問題の間違った解決策だからです。リソースのタイプをいじるのは悪い考えです。
ブラッド

@NathanHornby-私はそれに投票しませんでしたが、.htaccessを使用しないため、これはどのWindowsホストサイトでも機能しません。
PoloHoleSet 2018年

私は反対票を投じなかったが、この解決策はそのサフィックスのすべてのファイルに盲目的に影響を与える。それは無差別なので、すべての場合に適しているわけではありません。
JBH 2018

6

一部のブラウザー設定またはプラグインは、単純なWebページのように同じウィンドウで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>

参照元:このブログ


7
これは、注意を払っている人にサーバー上のすべてのファイルを提供するための良い方法のようです。 download.php?file=database_password_file.php例えば。
pbarney

5

以下のコードを.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);

1
これは、WebサーバーがApacheであると想定していませんか?
Peter Mortensen


4

本当になどを外部のダウンロードサイトを使用したり、ヘッダーを変更することなく、これを達成するための簡単な方法は、単にZIPファイルにPDFの内部と直接リンクしてZIPファイルを作成することです。これにより、常に[保存/開く]ダイアログがトリガーされます。.zipに関連付けられているプログラムが起動されるPDFウィンドウをダブルクリックするのは簡単です。

ところですばらしい質問です。ほとんどのブラウザー組み込みPDFプラグインは、何かを表示するのに非常に時間がかかります(PDFの読み込み中にブラウザーがハングすることが多いため)。


31
ひどい使いやすさ。多くのエンドユーザーは、zipファイルの処理方法を知りません。
CodeWarrior 2014

1
時々、単純な解決策が最善の解決策です!
elrado 2015年

1
良い解決策ではありません。私はFirefoxとZIPファイルでまさにその問題を抱えています。私は何をすべきか?ファイルを圧縮しますか?その場合、HTTPヘッダーを変更することで解決できる可能性がありますが、私はそれにアクセスできません。
Arnaud Weil

2

「ダウンロード」属性がすべてのブラウザに実装されるまで、サーバー側のソリューションはより互換性があります。

Pythonの例の1つは、ファイルストアのカスタム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()

2

これを行う非常に簡単な方法は、ページ上の1つのリンクを強制的にダウンロードする必要がある場合、href-linkでHTML5ダウンロード属性を使用することです。

参照:http : //davidwalsh.name/download-attribute

これにより、ユーザーがダウンロードするファイルの名前を変更でき、同時にダウンロードを強制できます。

これが良い習慣であるかどうかについては議論がありましたが、私の場合、PDFファイル用の埋め込みビューアーがあり、ビューアーにダウンロードリンクが提供されていないため、個別に提供する必要があります。ここで、ユーザーがPDFをWebブラウザーで開かないようにします。これは混乱を招くでしょう。

これは、ダイアログとして保存を開く必要はありませんが、プリセットのダウンロード先にリンクを直接ダウンロードします。もちろん、誰かのためにサイトを作成していて、リンクに手動で属性を書き込む必要がある場合は、おそらく悪い考えですが、属性をリンクに取り込む方法がある場合、これは簡単な解決策になる可能性があります。


1

これは古い投稿ですが、jQueryライブラリを使用するJavaScriptでの私の解決策は次のとおりです。

<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>

タグforce-download内でクラスを使用するだけで、<a>自動的にダウンロードが強制されます。親に追加することもでき、そのdiv中のすべてのリンクをピックアップします。

例:

<a href="/some/good/url/Post-Injection_Post-Surgery_Instructions.pdf" class="force-download" target="_blank">Download PDF</a>

これは、WordPressやその他のシステムやカスタムWebサイトに最適です。


0

追加するHTMLコードのファイル名の後に ?forcedownload=1

これは、ダイアログボックスをトリガーして保存またはダウンロードする最も簡単な方法です。


0

あなたがPDFファイルを開く方法を知っているブラウザ内にプラグインがある場合、それは直接開きます。画像やHTMLコンテンツの場合と同様です。

したがって、代替のアプローチは、応答でMIMEタイプを送信しないことです。このようにして、ブラウザはどのプラグインがそれを開くべきかを決して知りません。したがって、[ 保存/開く ]ダイアログボックスが表示されます。


MIMEタイプを送信するサーバーであり、PDFファイルに直接リンクする場合はヘッダーを変更できないため、これを実現するのは困難です。
Karel Petranek

0

ZIPファイル内のファイルへのダウンロードリンクを作成する必要があるという追加の問題で、非常によく似た問題が発生しました。

最初に一時ファイルを作成してから、一時ファイルへのリンクを提供しましたが、一部のブラウザーではダウンロードを提供するのではなく、コンテンツ(CSV Excelファイル)のみを表示することがわかりました。最終的には、サーブレットを使用して解決策を見つけました。これはTomcatとGlassFishの両方で機能し、私はInternet Explorer 10とChromeで試しました。

サーブレットは、ZIPファイルへのフルパス名と、ダウンロードする必要があるzip内のファイル名を入力として受け取ります。

JSPファイル内に、zip内のすべてのファイルを表示するテーブルと、次のようなリンクがあります。 onclick='download?zip=<%=zip%>&csv=<%=csv%>'

サーブレットコードは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


0

応答ヘッダーContent-Disposition:attachmentを追加します。続いてファイル名。Meta Content-Disposition; Inline;を削除します。同じウィンドウでドキュメントを開きます

javaでは次のように設定されています

response.setHeader("Content-Disposition", "attachment;filename=test.jpg");

-2

大きなPDFファイルを使用すると、ブラウザがハングします。Mozillaで、メニューの[ ツール ] →[ オプション ] →[ アプリケーション ]をクリックし、コンテンツタイプの横にAdobe Acrobatドキュメントを表示します。[アクション]プルダウンで、[ 常に確認]を選択します

これは私にとってはうまくいかなかったので、うまくいったのは:

メニューツール*→ アドオンAdobe Acrobat(Firefox用Adobe PDFプラグイン)→DISABLE。これで電子書籍をダウンロードできるようになりました。


2
質問を読みましたか これはクロスブラウザの回答ではありません
マーク

1
@markこれは、ユーザーがWebサイトの所有者ではなく、PDFの強制ダウンロードを促すための指示でもあります。
Nathan Hornby
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.