項目中的那些事---下載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文檔的需求中總結出的,本以為是個很簡單的功能,沒想到當它涉及到瀏覽器時竟有如此多的學問。

?

轉載于:https://www.cnblogs.com/hellowhy/p/6395147.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/255390.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/255390.shtml
英文地址,請注明出處:http://en.pswp.cn/news/255390.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL日志分類及性能分析你應該知道的知識

為什么80%的碼農都做不了架構師&#xff1f;>>> MySQL日志記錄了MySQL數據庫日常操作和錯誤信息&#xff0c;MySQL總共有四種類型的日志&#xff0c;通過分析這些日志可以查詢到MySQL的運行情況、用戶操作、錯誤信息等&#xff0c;可以為MySQL的管理和優化提供必要…

利用三個點(trsf)來實現各種規則圖形的實現

在Val3,是使用trsf(x,y,z,rx,ry,rz)來實現三維空間點的位置與方向。 其中第一點和第二點位置很重要&#xff0c;第三點是用來確定方向。根據這三個點先確定一個用戶坐標系。 在這個坐標系中&#xff0c;實現圓&#xff0c;三角形&#xff0c;矩形&#xff0c;腰圓&#xff0c;正…

android基礎組件----Button的使用

按鈕由文本或圖標&#xff08;或文本和一個圖標&#xff09;組成&#xff0c;當用戶觸摸到它時&#xff0c;會發生一些動作。今天我們開始Button的學習。少年的愛情永遠不夠用&#xff0c;一杯酒足以了卻一件心事。 Button的簡要說明 根據你是否想要一個帶有文本的按鈕&#xf…

@Repository、@Service、@Controller 和 @Component

Repository 、Service 、 Controller 、Component 這四個Spring注解 ,用于把加了注解的 類 加入到Spring 容器中管理&#xff0c;節省了xml 的繁重的配置&#xff0c;盡管如此xml 同樣可以實現&#xff08;一般建議先搞懂xml&#xff09;。 Repository Repository注解便屬于最先…

【pyqt5學習】——QTextEdit控件學習:獲取文本、添加文本

目錄 1、QTextEdit控件介紹 2、QTextEdit控件添加文本、添加HTML格式 3、QTextEdit控件獲取文本、獲取HTML格式文本 4、案例 1&#xff09;完整代碼 2&#xff09;效果 1、QTextEdit控件介紹 QTextEdit控件是一個支持多行輸入的輸入框&#xff0c;支持HTML進行格式的設置 2…

空間變化

空間變化 第一種&#xff1a;圓 第二種: 矩形 第三種&#xff1a;正五邊形 第四種:正六邊形 第五種&#xff1a;腰圓 算法&#xff1a; 在規則圖形&#xff08;不包括圓心-直徑法&#xff09;中&#xff0c;等于或者超過三個點。一般的&#xff0c;利用p1,p2,p3來建立一個用戶…

【pyqt5學習】——QAbstractButton學習(普通按鈕QPushButton、工具按鈕QToolButton、單選按鈕QRadioButton、復選框按鈕QCheckBox)

目錄 1、按鈕介紹 2、普通按鈕QPushButton學習 1&#xff09;特殊模式——開關按鈕&#xff08;toggle&#xff09; ①將按鈕設置為可選擇的 ②將按鈕按下 判斷按鈕是否被按下 isChecked() 2&#xff09;給按鈕設置前置圖標setIcon() ?編輯 3&#xff09;按鈕信號 4)完…

java 企業 網站源碼 模版 屏幕自適應 有前后臺 springmvc SSM 生成靜態化

前臺&#xff1a; 支持四套模版&#xff0c; 可以在后臺切換點擊&#xff1a;獲取地址QQ 313596790官網 http://www.fhadmin.org/系統介紹&#xff1a;1.網站后臺采用主流的 SSM 框架 jsp JSTL&#xff0c;網站后臺采用freemaker靜態化模版引擎生成html2.因為是生成的html&…

挖財后端架構簡介

挖財后端技術用的主要是比較大眾的東西&#xff0c;Web容器用Tomcat&#xff0c;框架主要是Spring MVC&#xff0c;也有少量的Play&#xff0c;中間服務層是Dubbo&#xff0c;微容器用Spring Boot&#xff0c;服務注冊這一塊是用ZooKeeper&#xff0c;核心業務開發方式還是圍繞…

【pyqt5學習】——QcomboBox學習

目錄 1、添加條目&#xff1a; 1)逐一添加 2&#xff09;批量添加 3&#xff09;獲取當前選中的索引 4&#xff09;獲取當前選中文本 5&#xff09;根據索引獲取文本 6&#xff09;統計條目總數 7&#xff09;信號——當前選中的索引發生改變currentIndexChanged() 2、…

vSphere Client 編輯虛擬機屬性的問題

vSphere Client 編輯虛擬機屬性的問題 編輯虛擬機屬性的時候&#xff0c; 出現&#xff1a; vpxclient.vmconfig.cpuid 初始值設置異常之類的&#xff0c;重置了&#xff0c; 并將注冊表中的所有vmvare 相關鍵值刪除了&#xff0c; 還是一樣的。。 后面參照https://kb.vmware.c…

Val編程-系統架構

利用Val可以編寫相對大型軟件。 界面書寫&#xff0c;運動軌跡規劃&#xff0c;外部通訊&#xff0c;進程交互&#xff0c;文本讀寫.... GlobalData可以利用一個庫來作為一個公用庫&#xff0c;實現各個庫的數據交互。 PublicFunc書寫基本的通用函數來作為基本函數&#xff0c;…

poj 1256 Anagram—next_permutation的神奇應用

題意&#xff1a;給你一條字符串&#xff0c;讓你輸出字符串中字符的全排列&#xff0c;輸出的順序要按它給的奇葩的字典序。 題解&#xff1a;要輸出全排列&#xff0c;暴力dfs可以過&#xff0c;但要注意題目的字典序以及相同字符的情況。如果用next_permutation()處理可以簡…

【pyqt5學習】—— 滑動條Qslider、計數器QSpinBox學習

目錄 1、滑動條QSlider 1)常用屬性 2&#xff09;實例——利用滑動條來實現字體大小的修改 ?編輯 2、計數器QSpinBox 1&#xff09;屬性方法 2&#xff09;實例 1、滑動條QSlider 1)常用屬性 self.slider QSlider(Qt.Horizontal)# 設置最小值self.slider.setMinimum(2)…

shell常用命令之curl: -w,–write-out參數詳解

顧名思義&#xff0c;write-out的作用就是輸出點什么。curl的-w參數用于在一次完整且成功的操作后輸出指定格式的內容到標準輸出。 輸出格式由普通字符串和任意數量的變量組成&#xff0c;輸出變量需要按照%{variable_name}的格式&#xff0c;如果需要輸出%&#xff0c;double一…

Val編程-速度因子

機械手臂在一個三個基本指令&#xff08;movel,movej,movec&#xff09;指令中有下面基本參數進行配置。 1. Frame toolField; Tcp的值2. Frame frameField;用戶坐標系的值3. MoveType absRelField;絕對運動與相對運動4. Config configField;姿態5. BlendType blendTypeField;倒…

Node.js學習之路24——Express框架的app對象

1.express() 基于Node.js平臺&#xff0c;快速、開放、極簡的web開發框架。創建一個Express應用.express()是一個由express模塊導出的入口top-level函數.const express require(express); let app express(); 1.1 靜態資源管理 express.static(root, [options]) express.stat…

【pyqt5學習】——對話框QDialog學習(QMessageBox、QColorDialog、QFIleDialog、QFontDialog、QInputDialog)

目錄 1、對話框QDialog類別 2、通用對話框 ?編輯 3、消息對話框QMessageBox() 1&#xff09;消息對話框QMessageBox類型 2&#xff09;案例 ?編輯 4、輸入對話框QInputDialog 1) 類型 2&#xff09;案例 5、字體格式對話框QFontDialog 6、顏色對話框QColorDialog 1&…

使用 Mesos 管理虛擬機

摘要 為了滿足渲染、基因測序等計算密集型服務的需求&#xff0c;UCloud 推出了“計算工廠”產品&#xff0c;讓用戶可以快速創建大量的計算資源&#xff08;虛擬機&#xff09;。該產品的背后&#xff0c;是一套基于 Mesos 的計算資源管理系統。本文簡要介紹該系統的結構、Mes…

Swift數據類型_整型和浮點型

//swift中的整型和浮點型/***//類型推斷整數是Int 浮點數是Double ,日常使用需要注意不能越界,存儲時間毫秒數 英雄經驗數等等之類內容容易越界整型大多數情況下&#xff0c;你不需要在代碼中指定哪種整型。Swift提供了一種額外的整型&#xff0c;Int類型Java中的long型&#x…