熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> PHP編程 >> 正文

讓PHP更快的為用戶提供文件下載

2022-06-13   來源: PHP編程 

    一般來說我們可以通過直接讓URL指向一個位於Document Root下面的文件來引導用戶下載文件

  
但是這樣做就沒辦法做一些統計權限檢查等等的工作於是很多時候我們采用讓PHP來做轉發為用戶提供文件下載

  
$file = “/tmp/dummytargz”

  
header(“Contenttype application/octetstream”)

  
header(ContentDisposition attachment filename=“ basename($file) )

  
header(“ContentLength filesize($file))

  
readfile($file)

  
但是這個有一個問題就是如果文件是中文名的話有的用戶可能下載後的文件名是亂碼

  
於是我們做一下修改(參考

  
$file = “/tmp/中文名targz”

  
$filename = basename($file)

  
header(“Contenttype application/octetstream”)

  
//處理中文文件名

  
$ua = $_SERVER[“HTTP_USER_AGENT”]

  
$encoded_filename = urlencode($filename)

  
$encoded_filename = str_replace(“+” “% $encoded_filename)

  
if (preg_match(“/MSIE/” $ua)) {

  
header(ContentDisposition attachment filename=“ $encoded_filename )

  
} else if (preg_match(“/Firefox/” $ua)) {

  
header(“ContentDisposition attachment filename*=”utf $filename )

  
} else {

  
header(ContentDisposition attachment filename=“ $filename )

  
}

  
header(ContentDisposition attachment filename=“ $filename )

  
header(“ContentLength filesize($file))

  
readfile($file)

  
輸出的時候如果是Apache + PHP mod那麼還需要發送到Apache的輸出緩沖區最後才發送給用戶而對於Nginx + fpm如果他們分開部署的話那還會帶來額外的網絡IO

  
現在看起來好多了不過還有一個問題那就是readfile雖然PHP的readfile嘗試實現的盡量高效不占用PHP本身的內存但是實際上它還是需要采用MMAP(如果支持)或者是一個固定的buffer去循環讀取文件直接輸出

    那麼能不能不經過PHP這層直接讓Webserver直接把文件發送給用戶呢?

  
今天我看到了一個有意思的文章How I PHPXSendFile

  
我們可以使用Apache的module mod_xsendfile讓Apache直接發送這個文件給用戶

  
$file = “/tmp/中文名targz”

  
$filename = basename($file)

  
header(“Contenttype application/octetstream”)

  
//處理中文文件名

  
$ua = $_SERVER[“HTTP_USER_AGENT”]

  
$encoded_filename = urlencode($filename)

  
$encoded_filename = str_replace(“+” “% $encoded_filename)

  
if (preg_match(“/MSIE/” $ua)) {

  
header(ContentDisposition attachment filename=“ $encoded_filename )

  
} else if (preg_match(“/Firefox/” $ua)) {

  
header(“ContentDisposition attachment filename*=”utf $filename )

  
} else {

  
header(ContentDisposition attachment filename=“ $filename )

  
}

  
header(ContentDisposition attachment filename=“ basename($file) )

  
//讓Xsendfile發送文件

  
header(“XSendfile $file”)

  
Lighttpd和Nginx也有類似的模塊大家有興趣的可以去找找看XSendfile頭將被Apache處理並且把響應的文件直接發送給Client


From:http://tw.wingwit.com/Article/program/PHP/201311/21065.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.