拆解 **X-Sendfile (Apache)** 與 **X-Accel-Redirect (NGINX)** 的差異、作用,以及如何在 Laravel 中應用。
---
## 📌 1. 作用
這兩個 header 的用途一樣:**把檔案傳送的工作交給 Web 伺服器本身來處理,而不是由 PHP (Laravel) 讀取後輸出。**
### 🔹 一般情況(沒有用 X-Sendfile / X-Accel-Redirect)
Laravel -> `Storage::get()` 讀取檔案內容 -> PHP 輸出 -> Apache/Nginx 傳給使用者。
❌ 問題:
* PHP 會佔用大量記憶體 (大檔案很危險)。
* PHP 會拖慢回應時間。
---
### 🔹 使用 X-Sendfile / X-Accel-Redirect
Laravel 只回應「檔案在哪裡」,Web 伺服器去讀取並直接送出檔案。
✅ 好處:
* 節省 PHP 記憶體、CPU。
* 利用 Web 伺服器的高效能檔案處理。
* 適合下載大檔案或影音串流。
---
## 📌 2. 差異
* **Apache → X-Sendfile**
* 需要安裝 `mod_xsendfile` 模組。
* PHP 設定 response header:
```http
X-Sendfile: /absolute/path/to/file.zip
```
* Apache 會攔截並傳送該檔案內容。
* **NGINX → X-Accel-Redirect**
* 內建支援,需設定一個內部 `location` 區塊。
* PHP 設定 response header:
```http
X-Accel-Redirect: /protected/file.zip
```
* NGINX 會將 `/protected/` 映射到實際檔案系統路徑。
---
## 📌 3. 在 Laravel 的應用
Laravel 沒有直接內建,但可以透過 **自訂 Response**。
### 🔹 Apache (X-Sendfile)
在 `app/Http/Controllers/DownloadController.php`:
```php
public function download($filename)
{
$path = storage_path('app/private/' . $filename);
if (!file_exists($path)) {
abort(404);
}
return response()
->noContent()
->header('X-Sendfile', $path)
->header('Content-Type', mime_content_type($path))
->header('Content-Disposition', 'attachment; filename="' . basename($path) . '"');
}
```
Apache `httpd.conf` 或 vhost:
```apache
XSendFile On
XSendFilePath /var/www/storage/app/private
```
---
### 🔹 NGINX (X-Accel-Redirect)
`app/Http/Controllers/DownloadController.php`:
```php
public function download($filename)
{
$path = '/protected/' . $filename; // NGINX location 會處理
return response()
->noContent()
->header('X-Accel-Redirect', $path)
->header('Content-Type', mime_content_type(storage_path('app/private/' . $filename)))
->header('Content-Disposition', 'attachment; filename="' . $filename . '"');
}
```
Nginx 設定 (`nginx.conf` 或 site conf):
```nginx
location /protected/ {
internal;
alias /var/www/storage/app/private/;
}
```
這樣 `/protected/file.zip` 只有 Nginx 可讀,外部無法直接訪問,必須經過 Laravel 控制器授權後再回應。
---
## 📌 4. 適用場景
* 大檔案下載(影片、zip、pdf)。
* 使用者授權後才允許下載的檔案。
* 減少 PHP 負擔(避免 memory limit)。
---
👉 總結:
* **X-Sendfile (Apache)** 與 **X-Accel-Redirect (NGINX)** 都是 **「PHP 不傳檔案,讓 Web Server 幫你傳」**。
* Laravel 可以透過回應 header 控制,並配合伺服器設定,達到 **安全且高效的大檔案下載**。