safari下載文件自動(dòng)加了html后綴問題
如何下載文件?
方法一、直接通過nginx下載靜態(tài)文件
如果文件是保存在服務(wù)器上面的,可以直接用nginx下載文件
比如說可以供用戶下載pdf文件,那么我的nginx配置可以是這樣子的:
location ~ /document/(.*)\.pdf$ {
root /home/nemo/myfile;
try_files /$uri 404;
}
按照上面的配置,當(dāng)我請(qǐng)求 http://fbd.intelleeegooo.cc/document/test.pdf 的時(shí)候,我服務(wù)器上的位于 /home/nemo/myfile/document/test.pdf 的這個(gè)文件就被下載了。當(dāng)找不到相應(yīng)的文件的時(shí)候,就會(huì)返回 404 。
方法二、通過php讀取文件并下載
但上面這種方式是所有人都可以下載pdf文件的,假如說下載文件這個(gè)動(dòng)作是與賬號(hào)有關(guān)的,比如說某用戶只能下載某些文件,那么就需要在php里面對(duì)用戶賬戶進(jìn)行處理并且下載相關(guān)文件。
看我在index.php里面這段示例代碼,這段代碼的功能下載test.txt文件
<?php $filePath = '/home/nemo/fun/testdownloadfile/test.txt'; $fileName = 'test.txt'; readfile($filePath);
比如說我開了一個(gè)8764端口,nginx配置如下:
server {
listen 8764;
server_name xx.xx.xx;
……
……
……
location / {
root /home/nemo/fun/testdownloadfile;
fastcgi_pass 127.0.0.1:xxxx;
fastcgi_index index.php;
include fastcgi.conf;
}
}
配置文件里面的 fastcgi_pass 后面可以是ip+端口,也可以是unix_socket的路徑。具體根據(jù)你安裝的php的里面的 php-fpm.conf 的 listen 來決定。
我們用 command + option + i 快捷鍵打開瀏覽器的調(diào)試模式,當(dāng)我在瀏覽器里面請(qǐng)求 http://xx.xx.xx:8764/ 的時(shí)候,結(jié)果是瀏覽器直接把txt文件的內(nèi)容顯示在了頁面上。
看一下調(diào)試模式里面的這個(gè)請(qǐng)求,它的response header如下:

可以看到它里面的 Content-Type 是 text/html ,表示是一個(gè)html文件,所以瀏覽器就直接展示在頁面上了?!娟P(guān)于常用的一些 Content-Type ,可以見本文最后】
那么我改一下代碼,在里面設(shè)置一下header,示例代碼如下:
<?php
$filePath = '/home/nemo/fun/testdownloadfile/test.txt';
$fileName = 'test.txt';
header('Content-Disposition: attachment; filename=' . $fileName);
readfile($filePath);
我在chrome里面新建一個(gè)tab頁輸入url http://fbd.intelleeegooo.cc/document/test.pdf 的時(shí)候,成功下載了這個(gè)文件,如下圖所示:

但是我在safari里面的時(shí)候,下載下來的文件多了一個(gè) html 后綴,如下圖所示

我再改下代碼,設(shè)置 Content-Type ,看如下示例代碼:
<?php
$filePath = '/home/nemo/fun/testdownloadfile/test.txt';
$fileName = 'test.txt';
header('Content-Type: application/octet-stream;charset=utf-8');
header('Content-Disposition: attachment; filename=' . $fileName);
readfile($filePath);
這樣改過之后,在safari里面下載的文件就是正常的了,不帶html后綴的。
2.2 在php里面讀取并輸出文件的幾種方法
在設(shè)置完header信息之后,下面幾種方法都可以用來輸出文件
file_get_contents() ,這個(gè)方法是把文件的內(nèi)容以字符串的形式全部讀取到內(nèi)存里面。當(dāng)文件比較大的時(shí)候,會(huì)超過內(nèi)存限制
$content = file_get_contents($filePath);
echo $content;
file() ,將文件以行的形式全部讀取到數(shù)組中。當(dāng)文件比較大的時(shí)候,會(huì)超過內(nèi)存限制
$f = file($filePath);
while(list($line, $content) = each($f)) { // $line是int類型表示是第幾行(從0開始), $content是字符串類型表示這一行的內(nèi)容
echo $content;
}
readfile() ,讀取文件并且寫入到輸出緩沖區(qū)。這種方式可以輸出大文件,讀取單個(gè)文件不會(huì)超出內(nèi)存限制。
ob_end_clean();
readfile($filePath);

readfile自身不會(huì)導(dǎo)致任何內(nèi)存問題。如果出現(xiàn)內(nèi)存不足的問題,使用 ob_get_level() 確保輸出緩存已經(jīng)關(guān)閉。
但 readfile() 方法還是可以會(huì)引起內(nèi)存耗盡
readfile實(shí)際上還是需要采用MMAP(如果支持), 或者是一個(gè)固定的buffer去循環(huán)讀取文件, 直接輸出。
fopen() ,這就類似于C語言里面的讀取文件。fopen每次可以指定讀取某個(gè)塊大小的內(nèi)容,可以讀入大文件。不會(huì)超過內(nèi)存限制
$file = @fopen($filePath,"rb");
while(!feof($file)) {
print(@fread($file, 1024*8));
ob_flush();
flush();
}
2.3 內(nèi)存限制
在php的配置文件 php.ini 里面,有一個(gè) memory_limit 這個(gè)設(shè)置項(xiàng),設(shè)置的是每個(gè)腳本可以分配的內(nèi)存。
如下圖所示,我自己放寬了一點(diǎn)變成了256M,默認(rèn)是128M

正如上面所說,讀取大文件的時(shí)候,可能會(huì)內(nèi)存耗盡。
php里面有 ini_set() 方法可以在腳本運(yùn)行時(shí)保持新的值,在腳本結(jié)束時(shí)恢復(fù)。
并不是 php.ini 里面的所有設(shè)置項(xiàng)都可以被修改,所有可以被 ini_set() 修改的選項(xiàng)可以從 官方手冊(cè)里面的這個(gè)清單 知曉
有一種方法可以在執(zhí)行的時(shí)候動(dòng)態(tài)的修改腳本可以使用的內(nèi)存大小,而不一定非要修改php.ini文件,畢竟php.ini是針對(duì)全局的。
在腳本里面動(dòng)態(tài)的修改一些設(shè)置,只對(duì)該腳本有效,實(shí)際上并不真正地修改 php.ini 文件。
2.5 時(shí)間限制
一般情況下,使用php下載文件的時(shí)候,會(huì)加上一行 set_time_limit(0); ,表示不限制這個(gè)php腳本執(zhí)行的時(shí)間
<?php
$filePath = '/home/nemo/fun/testdownloadfile/test.txt';
$fileName = 'test.txt';
set_time_limit(0);
header('Content-Type: application/octet-stream;charset=utf-8');
header('Content-Disposition: attachment; filename=' . $fileName);
readfile($filePath);
看下 官方手冊(cè)上 的解釋

Content-Disposition 相關(guān)解釋
在常規(guī)的HTTP應(yīng)答中, Content-Disposition 消息頭指示回復(fù)的內(nèi)容該以何種形式展示,是以內(nèi)聯(lián)的形式(即網(wǎng)頁或者頁面的一部分),還是以附件的形式下載并保存到本地
Content-Disposition 消息頭最初是在MIME標(biāo)準(zhǔn)中定義的,HTTP表單及POST 請(qǐng)求只用到了其所有參數(shù)的一個(gè)子集。只有form-data以及可選的name和filename三個(gè)參數(shù)可以應(yīng)用在HTTP場(chǎng)景中
inline
inline展示txt文件
看如下示例代碼,設(shè)置inline內(nèi)聯(lián),將上面的test.txt文件在瀏覽器里面展示
<?php
$filePath = '/home/nemo/fun/testdownloadfile/test.txt';
$fileName = 'test.txt';
header('Content-Disposition: inline; filename=' . $fileName);
readfile($filePath);
常用的幾種 Content-Type 類型
下面列一下常用的幾種Content-Type
- text/html ,內(nèi)容是html格式
- text/plain ,內(nèi)容是純文本格式
- image/gif , gif圖片格式
- image/jpeg , jpg圖片格式
- image/png , png圖片格式
- multipart/form-data ,常見的 POST 數(shù)據(jù)提交的方式。當(dāng)需要上傳文件時(shí),會(huì)用到這種類型
- application/json ,消息主體是序列化后的 JSON 字符串
- application/octet-stream ,二進(jìn)制流數(shù)據(jù)。一般在下載文件的時(shí)候比較常見
- application/x-www-form-urlencoded , 瀏覽器的原生form表單,提交的數(shù)據(jù)按照 key1=val1&key2=val2 的方式進(jìn)行編碼,key和val都進(jìn)行了URL轉(zhuǎn)碼
總結(jié)
以上所述是小編給大家介紹的safari下載文件自動(dòng)加了html后綴問題,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Laravel框架實(shí)現(xiàn)的上傳圖片到七牛功能詳解
這篇文章主要介紹了Laravel框架實(shí)現(xiàn)的上傳圖片到七牛功能,結(jié)合實(shí)例形式詳細(xì)分析了七牛擴(kuò)展包相關(guān)安裝、配置及操作Laravel上傳圖片到七牛的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-09-09
Laravel 5框架學(xué)習(xí)之向視圖傳送數(shù)據(jù)
本文向大家展示的是Laravel5框架學(xué)習(xí)系列的第三篇文章,給大家講解的是如何向視圖傳送數(shù)據(jù),從無到有,十分細(xì)致,有需要的小伙伴可以參考下。2015-04-04
淺談PHP array_search 和 in_array 函數(shù)效率問題
這篇文章主要介紹了淺談PHP array_search 和 in_array 函數(shù)效率問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
php使用get和post傳遞數(shù)據(jù)出現(xiàn)414?Request-URI?Too?Large的原因分析及解決方案
Request-URI Too Large(請(qǐng)求URI過長(zhǎng))是一個(gè)HTTP錯(cuò)誤狀態(tài)碼,表示所發(fā)送的HTTP請(qǐng)求中的URI(統(tǒng)一資源標(biāo)識(shí)符)長(zhǎng)度超過了服務(wù)器能夠處理的限制,這篇文章主要介紹了php使用get和post傳遞數(shù)據(jù)出現(xiàn)414?Request-URI Too?Large的解決方案,需要的朋友可以參考下2023-08-08
Laravel 5框架學(xué)習(xí)之?dāng)?shù)據(jù)庫遷移(Migrations)
本文給大家介紹的是Laravel5框架中最強(qiáng)大的功能之一數(shù)據(jù)庫遷移(database migrations),本文詳細(xì)給大家介紹數(shù)據(jù)庫遷移的步驟和方法,非常實(shí)用,有需要的小伙伴可以參考下。2015-04-04
php反序列化長(zhǎng)度變化尾部字符串逃逸(0CTF-2016-piapiapia)
這篇文章主要介紹了0CTF-2016-piapiapia(php反序列化長(zhǎng)度變化尾部字符串逃逸),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
Laravel框架Auth用戶認(rèn)證操作實(shí)例分析
這篇文章主要介紹了Laravel框架Auth用戶認(rèn)證操作,結(jié)合實(shí)例形式分析了Auth用戶認(rèn)證的相關(guān)操作步驟、實(shí)現(xiàn)技巧與使用注意事項(xiàng),需要的朋友可以參考下2019-09-09

