項目中的那些事---下載pdf文件


   最近做了一個下載pdf文檔的需求,本以為使用HTML5中<a>標簽的屬性download就能簡單搞定,不料IE竟然不支持這一簡單粗暴的H5新特性,而是直接在網頁中打開,

於是各種搜索之后得出以下結論:IE中下載文檔時,要想直接下載而不是在瀏覽器中打開,就要給下載的請求添加一些header屬性:

1、Content-Disposition: attachment; filename=filename
2、Content-Type: application/octet-stream;

 

現在以我做的項目為例,總結一下在IE中下載pdf等類型文檔的方法:

1、服務器端語言:PHP

2、前端語言:Jquery

因為要設置header,所以只能走服務器

第一步:前端創建一個下載文件的按鈕

<button class="btn btn-small btn-warning"  id="df">下載pdf文檔</button>

 這里面的class是bootstrap中的樣式,用過bootstrap的人應該都很熟悉,這里不再贅述

第二步:給這個按鈕添加點擊事件,當點擊該按鈕時發起一個下載文檔的請求給服務器

$("#df").click(function(){
    $.ajax({
        url:"downloadFile",
        type : 'POST',
        dataType : 'json',
        success : function (m) {
            if (m.status == 1) {
                location.href = "downloadFile"    
        } else {
                showAlert(m.info);
            }
        }
    });
});

這里使用ajax請求,downloadFile為請求的服務端方法,當服務器接收到該請求之后就會做出響應,即下一步

第三步:服務器接受並響應請求

public function downloadHelp(){
        /*設置文檔的路徑*/
    $fileDir = SERVER_PATH . 'static/help/';

        if (IS_POST) {
            if (!is_dir($fileDir)) {
                mkdir($fileDir, 0777, true);
            }
            
            $filePath = $fileDir . '下載文檔.pdf';

            if (!is_file($filePath)) {
                $this->ajax_return(0,"文檔不存在");
            } else if (!is_readable($filePath)) {
                $this->ajax_return(0,"文檔不可讀");
            } else {
                $this->ajax_return(1);
            }
        } else {
            $ua = $_SERVER["HTTP_USER_AGENT"];
            $fileName = '下載文檔.pdf';
            $encoded_filename = urlencode($fileName);
            $encoded_filename = str_replace("+", "%20", $encoded_filename);
            $url = $fileDir . $fileName;
            $fileSize = filesize($url);
             header("Cache-Control: private");
             header("Content-Type: application/octet-stream;");
             header("Accept-Ranges: bytes");
             header("Accept-Length: " . $fileSize * 1024);
             /*
              * 根據瀏覽器設置下載文件名稱為中文時的編碼
              */
             if (preg_match("/MSIE/", $ua) || strpos($ua,"rv:11.0")) { 
                 header('Content-Disposition: attachment; filename="' . $encoded_filename . '"'); 
             } else if (preg_match("/Firefox/", $ua)) { 
                 header('Content-Disposition: attachment; filename*="utf8\'\'' . $fileName . '"'); 
             } else { 
                 header('Content-Disposition: attachment; filename="' . $fileName . '"'); 
             } 
             
             readfile($url);
             exit;
        }
}    

上面代碼中的方法其實是完成了兩次客戶端請求,

1、第一次請求方式是POST(可見js代碼中的ajax請求),所以這時會判斷文件是否存在以及是否具有讀取權限等
2、第二次請求方式是GET,所以這時會根據第一次請求的結果決定下一步

     (1)當staus="0",,提示"文檔不存在" or "文檔不可讀" 

   (2)當status="1",設置header,並輸出文件

其中值得注意的是,當下載的文件名為中文,且字符編碼是UTF-8時,要根據瀏覽器類型進行設置,否則會出現文件名亂碼的情況,上面的代碼中已解決該問題,但是方法不止這一種,

所以再貼出解決下載文件名中文亂碼的兩種方法:

公共部分:
$ua = $_SERVER["HTTP_USER_AGENT"];
$fileName = '下載文檔.pdf';
$encoded_filename = urlencode($fileName);
$encoded_filename = str_replace("+", "%20", $encoded_filename);
$url = $fileDir . $fileName;

第一種方法:
if (strpos($ua,"MSIE") || strpos($ua,"rv:11.0")) {
       header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
 } else if (strpos($ua,"Firefox")) {
       header('Content-Disposition: attachment; filename*="utf8\'\'' . $fileName . '"');
 }else {
       header('Content-Disposition: attachment; filename="' . $fileName . '"');
 }

第二種方法:
if (preg_match("/MSIE/", $ua) || strpos($ua,"rv:11.0")) { 
       header('Content-Disposition: attachment; filename="' . $encoded_filename . '"'); 
} else if (preg_match("/Firefox/", $ua)) { 
       header('Content-Disposition: attachment; filename*="utf8\'\'' . $fileName . '"'); 
} else { 
       header('Content-Disposition: attachment; filename="' . $fileName . '"'); 
} 


其實這兩種方法本質上沒什么區別,只是我在測試的過程中發現,通過 $_SERVER["HTTP_USER_AGENT"]獲取的瀏覽器信息中,如果瀏覽器是IE(我用的是IE11),

就沒有“MSIE”這個字符串,導致即便是IE,strpos($ua,"MSIE")方法的結果還是false,所以無法解決IE中的亂碼問題,於是就用strpos($ua,"MSIE")和preg_match("/MSIE/", $ua) 兩種方法,

並在兩種方法中都加上 strpos($ua,"rv:11.0"),這樣才能判斷出是IE瀏覽器,也就能順利解決IE中文件名稱中文亂碼問題了。

以上就是本次下載pdf文檔的需求中總結出的,本以為是個很簡單的功能,沒想到當它涉及到瀏覽器時竟有如此多的學問。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM