Nginx和apache服务下载大文件,PHP X-sendfile扩展实现文件下载

本文介绍了一种通过调整PHP内存限制及使用X-sendfile模块实现的大文件高效下载方案,该方案适用于Nginx和Apache服务器,有效减少服务器资源消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网站中下载文件是一个经常用到的功能,可是看起来很简单的,做的时候各种问题出现,内心崩溃的有没有。。。

不多说我们进入正题

 

往往网上答案千篇一律是这样的:

//源文件路径 
$thefile='test.text'; 

//文件下载 
$fileinfo = pathinfo($filename); 
header('Content-type: application/x-'.$fileinfo['extension']);
header('Content-Disposition: attachment; 
filename='.$fileinfo['basename']);
header('Content-Length: '.filesize($filename));
readfile($thefile); exit();


或是这样的

//源文件路径
$thefile='test.text';
$filename=$thefile;
$file  =  fopen($filename, "rb");
Header( "Content-type:  application/octet-stream ");
Header( "Accept-Ranges:  bytes ");
Header( "Content-Disposition:  attachment;  filename= 4.doc");
$contents = "";
while (!feof($file)) {
    $contents .= fread($file, 8192);
}
fclose($file);

 

以上下载小文件完全没有问题,但是我要的是下载大文件,大文件,大文件,你就粘贴给我看这个???

于是我放弃了 某度,用了google。

 

1.首先 打开php.ini 查找 memory_limit  修改 你想占用内存,我服务器内存大所以调的高,看情况调整。

memory_limit = 1024M

好了我们来试试下载大文件

$file = fopen($file_dir,"r"); 

// 输入文件标签
Header("Content-type: application/octet-stream");
Header("Accept-Ranges: bytes");Header("Accept-Length: ".filesize($file_dir));
Header("Content-Disposition: attachment;
filename=" . $attach['name']);

// 输出文件内容
echo fread($file,filesize($file_dir));
fclose($file);
exit();

真的能下载几百兆文件了,好开心。但是我的网站怎么打不开了呢?what?什么鬼?你玩我吧?崩溃的边缘

 

好吧!我发现个问题:

这种方式可以实现文件的下载,但是这种下载方式相当耗资源,长期占用服务端脚本资源和服务器内存资源,消耗很大。 

php函数下载文件把php内存占用完了,怎么解决?

 

查阅资料,我们可以借助X-sendfile模块来实现更高效率的文件下载。 
 X-sendfile是现代操作系统支持的一种高性能网络IO方式,服务端脚本程序比如php负责构造请求头信息,然后下载的时候不需要php参与,web服务器直接处理X-Sendfile头信息,并且把响应的文件直接发送给浏览器客户端;这样避免了内存占用。

Nginx

Demo下载

<?php
/*
 * 使用说明:
 * 以phpStudy环境为例子
 * 在 Nginx 的配置文件 'vhosts.conf' 中修改,如没有vhosts.conf请在nginx.conf 中设置
 * 在对应的网站 server 中加入 "location"
server {

}

location /data/ {
    internal;   #禁止直接访问资源文件,如果要让正常访问请在 internal 前加上 # 号。
    alias	E:\dome\XSendfile\static\;  #挂载虚拟目录,"E:\dome\XSendfile\static\" 为真实存在的目录,"/data/"为虚拟网站目录
}
#也可以不使用虚拟目录
location /static/ {
    internal;   #禁止直接访问资源文件,如果要让正常访问请在 internal 前加上 # 号。
    root	E:\dome\;  #网站根目录
}

实例:
server {
    listen       80;
    server_name  127.0.0.2
    #####
    ~我省略就不写了~
    #####
    location /data/ {
        internal;
        alias	E:\dome\XSendfile\static\;
    }
}

!!!!配置完重启服务!!!
*/


//文件地址
$realPath = "/data/test_img.jpg";
//测试限速100KB
NginxDownloadFile($realPath,'', 100);

/**
 * @param string $realPath 文件路径
 * @param string $fileName 文件名,默认自动获取文件路径的文件名称
 * @param int $rate 下载速度限制Kb计算,默认1M/s, 0为不限速
 */
function NginxDownloadFile($realPath,$fileName='',$rate=1024){

    if (!$fileName){
        //获取文件名并处理文件名称
        $fileName = basename($realPath);
    }
    //处理ie中文文件名,避免文件名乱码
    $encoded_filename = rawurlencode($fileName);

    $ua = $_SERVER["HTTP_USER_AGENT"];
    header('Content-type: application/octet-stream');
    if (preg_match("/MSIE/", $ua)) {
        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 . '"');
    }

    //让Xsendfile发送文件
    header('X-Accel-Redirect: ' . $realPath);

    //限制下载速度 按字节计算 100KB = 1024 * 100,为0不限速
    if($rate){
        header('X-Accel-Limit-Rate: ' . 1024 * $rate);
    }
    //是否开启缓冲 yes|no
    //header('X-Accel-Buffering: yes' );
    //字符集
    //header('X-Accel-Charset: utf-8' );
    exit;
}

 

Apache

首先我们要查看Apache的版本信息:phpinfo();

然后下载对应的X-sendfile模块包(下载地址:https://github.com/nmaier/mod_xsendfile)。

Linux安装方法:

我的是centos

参考地址:http://blogs.isb.bj.edu.cn/miles/2014/02/20/installing-mod_xsendfile-on-centos-6/

yum install mod_xsendfile

1.打开如下路劲,里面有个xsendfile.conf(前提是你安装mod成功后)

> cd /etc/httpd/conf.modules.d

2.vi打开xsendfile.conf,添加如下两行,保存退出(:wq),重启httpd(systemctl restart httpd)

 

windows安装方法

1、将解压出来的mod_xsendfile.so文件拷贝到Apache的modules目录下,一定要选择相应的版本24就是2.4,22就是2.2


2、配置Apache的conf目录下的httpd.conf文件,加入以下代码:

LoadModule xsendfile_module modules/mod_xsendfile.so

XSendFile on
XSendFilePath F:/网站路径(或你的文件目录)

3、重启Apache服务,重启成功。

这些工作完成之后我们就可以借助X-sendfile来实现文件下载了:

$ua = $_SERVER["HTTP_USER_AGENT"];

$filename = $attach['name'];
$encoded_filename = urlencode($filename);
$encoded_filename = str_replace("+", "%20", $encoded_filename);

// 输入文件标签
$realpath =  realpath($file_dir);
header('Content-Type: application/octet-stream');


//处理中文文件名,避免文件名乱码
$encoded_filename = rawurlencode($filename);
if (preg_match("/MSIE/", $ua)) {
    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 . '"');
}

//让Xsendfile发送文件
header("X-Sendfile: $realpath");
exit();

 

好激动赶紧试试,下载大文件没问题,网站可以正常访问,要的就是这效果,嘎嘎嘎。

吐槽一下:某度很多都是复制粘贴一个字不多一个字不少,一毛一样,关键是他还没试过这代码有没有用,我真不知道这有什么意思

 

<think>首先,用户的问题是:“如何在服务器上部署代码以处理数据并下载处理后的文件”。这涉及到在服务器上部署代码来处理数据,然后允许用户下载处理后的文件。我需要参考提供的引用内容:-引用[1]:讨论了部署SpringBoot+Vue前后端分离项目。它涉及打包后端应用、构建前端静态文件、上传到服务器、配置Nginx作为反向代理。-引用[2]:关于UnityWebGL连接数据库,使用php文件部署在服务器端作为桥梁,C#代码连接php上传数据。-引用[3]:关于使用PyCharm远程连接服务器运行项目代码,特别是针对深度学习项目。用户的问题是关于部署代码处理数据并下载文件,这与引用[1][2]更相关,因为它涉及服务器端处理。关键步骤:1.**准备服务器环境**:确保服务器有必要的运行时环境,比如Python、Node.js、Java等,取决于代码语言。2.**部署代码**:将代码上传到服务器。这可以通过FTP、SCP、Git等方式。3.**处理数据**:在服务器上运行代码处理数据。处理后的文件应存储在服务器的某个目录。4.**允许下载**:配置Web服务器(如NginxApache)来提供文件下载,或者通过API端点返回文件。5.**安全性**:确保文件访问是安全的,可能需要身份验证。基于引用:-从引用[1]:Nginx可以用于反向代理静态文件服务-从引用[2]:使用php作为桥梁处理数据库交互,这可以扩展文件处理。-从引用[3]:远程连接服务器运行代码,这可以用于部署运行处理脚本。用户的具体需求是处理数据并下载文件。所以,我假设用户有代码(比如Python脚本)来处理数据,生成文件。一般方法:1.**上传代码到服务器**:使用SCP、SFTP或Git部署代码。2.**运行代码**:通过SSH远程执行脚本,或者设置守护进程。3.**存储输出文件**:在处理后,文件保存在服务器目录。4.**下载文件**:配置Web服务器提供文件访问,或使用FTP/SFTP下载。对于下载部分,常见方式:-通过HTTP服务:设置一个URL路径映射到文件目录。-通过API:后端代码提供端点来下载文件。既然用户提到“部署代码”,我应该提供一个清晰的步骤。结构化回答:-**步骤1:准备服务器环境**-**步骤2:部署代码**-**步骤3:运行代码处理数据**-**步骤4:配置文件下载**-**步骤5:访问下载文件**使用中文回答,因为指令要求中文。生成相关问题:在回答末尾,添加相关问题,类似示例。引用标识:在引用内容末尾添加[^1]等。但用户提供的引用是关于不同主题的,我需要确保引用相关。指令说“回答中引用的段落末尾自然地添加引用标识”,所以我应该在提到引用时添加。用户提供的引用:-[^1]:部署SpringBoot+Vue-[^2]:Unity连接数据库-[^3]:PyCharm远程连接服务器这些不是直接匹配用户问题,但有些元素相关。例如,引用[1]提到部署后端服务,引用[3]提到远程运行代码。我可以参考这些,但不要强行引用。指令说“上述引用仅供参考”,所以我可以基于它们构建。真实可靠的回答:基于我的知识。最终回答结构:-解释整体过程-详细步骤-代码示例(如果适用)-相关问题对于代码示例,用户问题没有指定语言,但假设是Python脚本处理数据。例如:-部署一个Python脚本处理数据。-运行后输出文件-配置Nginx提供文件下载。生成相关问题:1.如何确保服务器部署的安全性?2.如何处理大数据文件服务器上?3.如何自动化数据处理任务?类似示例的格式。</think>### 如何在服务器上部署代码处理数据并下载处理后的文件服务器上部署代码处理数据并下载文件涉及几个关键步骤:准备服务器环境、上传部署代码、运行数据处理任务、配置文件下载机制。整个过程需要确保服务器具备必要的运行时环境(如Python、Node.js、Java等),并通过Web服务器(如Nginx)或API提供文件访问。以下是详细步骤,基于真实可靠的部署实践(如引用[1][3]所述的环境准备远程连接方法)。 --- ### 步骤1: 准备服务器环境 在部署代码前,确保服务器满足运行要求: - **安装运行时环境**:根据代码语言安装依赖。例如: - Python项目:安装Python、pip及所需库(如Pandas用于数据处理)。 - Java项目:安装JDK构建工具(如Maven)。 - **安装Web服务器**:推荐使用NginxApache处理文件下载请求。 - **设置安全访问**:配置SSH密钥登录,避免密码泄露;使用防火墙(如UFW)限制端口访问。 - **创建专用目录**:为代码文件建立结构清晰的目录,例如: - `/home/user/code/`:存放代码脚本。 - `/home/user/data/`:存储原始数据输出文件。 引用[3]强调环境准备的重要性,包括安装必要工具确保网络连接稳定[^3]。 --- ### 步骤2: 上传部署代码 将本地代码上传到服务器,并确保其可执行: - **上传代码**:使用SCP、SFTP或Git工具上传文件。例如,通过SCP上传Python脚本: ```bash # 本地终端执行:上传script.py到服务器的/home/user/code/目录 scp -i ~/.ssh/your_key.pem script.py user@server_ip:/home/user/code/ ``` - **代码部署**:设置代码权限依赖: - 安装依赖:在服务器上运行 `pip install -r requirements.txt`(Python)或类似命令。 - 测试运行:通过SSH远程执行脚本验证功能: ```bash ssh user@server_ip "python /home/user/code/script.py" ``` 引用[3]提到PyCharm远程连接可简化部署,允许直接运行调试代码[^3]。 --- ### 步骤3: 运行代码处理数据 在服务器上执行代码处理数据,并保存输出文件- **手动或自动运行**: - 手动方式:SSH登录后运行脚本,例如处理数据并输出CSV文件: ```bash python /home/user/code/script.py --input /home/user/data/input.csv --output /home/user/data/output.csv ``` - 自动化方式:使用Cron定时任务或系统守护进程(如systemd)定期运行脚本。 - **处理逻辑示例**(Python): ```python # script.py:读取数据、处理、保存文件 import pandas as pd def process_data(input_path, output_path): data = pd.read_csv(input_path) # 数据处理逻辑,例如过滤或计算 processed_data = data[data['value'] > 100] processed_data.to_csv(output_path, index=False) print(f"文件已保存至: {output_path}") if __name__ == "__main__": import argparse parser = argparse.ArgumentParser() parser.add_argument("--input", required=True) parser.add_argument("--output", required=True) args = parser.parse_args() process_data(args.input, args.output) ``` 确保输出文件存储在指定目录(如`/home/user/data/`),并设置文件权限为可读(`chmod 644 output.csv`)。 --- ### 步骤4: 配置文件下载 配置Web服务器提供文件下载服务,确保用户可通过HTTP访问: - **使用Nginx设置静态文件服务**: 1. 编辑Nginx配置文件(`/etc/nginx/sites-available/default`): ```nginx server { listen 80; server_name your_domain.com; # 替换为服务器IP或域名 # 文件下载路径映射 location /downloads/ { alias /home/user/data/; autoindex on; # 允许列出目录文件 add_header Content-Disposition 'attachment'; # 强制下载而非预览 } } ``` 2. 重启Nginx:`sudo systemctl restart nginx`。 - **通过API下载**:如果使用后端框架(如Flask或Spring Boot),添加下载端点: ```python # Flask示例:提供文件下载API from flask import Flask, send_file app = Flask(__name__) @app.route('/download/<filename>') def download_file(filename): return send_file(f"/home/user/data/{filename}", as_attachment=True) if __name__ == "__main__": app.run(host='0.0.0.0', port=5000) ``` 引用[1]提到Nginx反向代理可高效处理文件请求[^1]。 --- ### 步骤5: 访问下载文件 用户通过浏览器或命令行下载处理后的文件- **HTTP下载**:访问URL如 `http://server_ip/downloads/output.csv` 直接下载- **命令行下载**:使用`wget`或`curl`: ```bash wget http://server_ip/downloads/output.csv ``` - **安全性增强**:添加身份验证(如Nginx的Basic Auth)或HTTPS加密。 --- ### 总结 整个过程包括环境准备、代码部署、数据处理文件下载配置。关键点: - **效率**:自动化脚本运行(Cron)减少手动干预。 - **可靠性**:测试环境与生产环境一致,避免依赖问题。 - **扩展性**:对于大数据处理,考虑使用消息队列(如RabbitMQ)或分布式框架。 如果代码涉及数据库交互(如引用[2]所述),可添加PHP或类似桥梁处理数据读写[^2]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值