Nginx使用X-Accel-Redirect实现静态文件下载的统计、鉴权、防盗链、限速等


Posted in Servers onApril 04, 2021

需求

  • 统计静态文件的下载次数;
  • 判断用户是否有下载权限;
  • 根据用户指定下载速度;
  • 根据Referer判断是否需要防盗链;
  • 根据用户属性限制下载速度;

X-Accel-Redirect

This allows you to handle authentication, logging or whatever else you please in your backend and then have NGINX handle serving the contents from redirected location to the end user, thus freeing up the backend to handle other requests. This feature is commonly known as X-Sendfile.
这个功能允许你在后端处理权限,日志或任何你想干的,Nginx提供内容服务给终端用户从重定向后的路径,因此可以释放后端去处理其他请求(直接由Nginx提供IO,而不是后端服务)。这个功能类似 X-Sendfile 。

不同 Web 服务器,相同功能,不同的标识:

nginx: X-Accel-Redirect 
squid: X-Accelerator-Vary 
apache: X-Sendfile 
lighttpd: X-Sendfile/X-LIGHTTPD-send-file 

X-Accel-Limit-Rate

限制下载速度,单位字节。默认不限速度。

X-Accel-Buffering

设置此连接的代理缓存,将此设置为no将允许适用于Comet和HTTP流式应用程序的无缓冲响应。将此设置为yes将允许响应被缓存。默认yes。

X-Accel-Expires

如果已传输过的文件被缓存下载,设置Nginx文件缓存过期时间,单位秒。默认不过期。

X-Accel-Charset

设置文件字符集,默认utf-8。

使用条件

  • 必须有Nginx作为后端服务的代理;
  • 必须访问Nginx的代理地址,直接访问后端服务Nginx会报404;
  • 可自行配置Content-Type来控制是下载(application/octet-stream)还是展示(image/jpeg等);

代码实现

  1. Nginx监听15555端口。
  2. Nginx代理后端服务的18000端口。
  3. 设置/file路径为internal,指定具体文件存储的磁盘位置。
  4. 后端服务接收到文件下载请求,处理业务逻辑后X-Accel-Redirect/file路径。
  5. Nginx收到后端返回信息中的X-Accel-Redirect请求头,接管文件下载任务。
  6. 请求路径:http://localhost:15555/f/1.jpg

Java-SpringMVC版本

Nginx配置

server {
    listen 15555;

    location / {
        proxy_redirect off;
        proxy_set_header Host  $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:18000/;            
    }

    location /file {
        internal;
        alias /data/file;
    }
}

Java代码

注意fileName添加:.+,或者获取不到文件后缀名。

@GetMapping(value = "/f/{fileName:.+}")
public void file(@PathVariable String fileName, HttpServletResponse response, HttpServletRequest request) throws IOException {
    //统计
    //鉴权
    //判断Referer
    String referer = request.getHeader("Referer");
    if (referer == null || !referer.startsWith("https://www.zhangbj.com")) {
        response.sendError(403, "Forbidden");
        return;
    }
    response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
    response.setHeader("Content-Type", "application/octet-stream");
    response.setHeader("X-Accel-Redirect","/file/" + fileName);
    response.setHeader("X-Accel-Limit-Rate","1024");//限速,单位字节,默认不限
    response.setHeader("X-Accel-Buffering","yes");//是否使用Nginx缓存,默认yes
}

PHP-ThinkPHP版本

Nginx配置

server {
    listen  80;
    server_name  localhost;
    root   D:/z-blog/public;
    location / {
        index  index.html index.htm index.php;
        if (!-e $request_filename) {
            rewrite  ^(.*)$  /index.php?s=/$1  last;
            break;
        }
    }

    location ~ \.php(.*)$ {
        fastcgi_pass   127.0.0.1:9500;
        fastcgi_index  index.php;
        fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  PATH_INFO  $fastcgi_path_info;
        fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
        include        fastcgi_params;
    }

    location /file {
        internal;
        alias D:/file;
    }
}

ThinkPHP代码

Router:

Route::get('/f/:fileName', 'index/File/file');

Controller:

<?php

namespace app\index\controller;

use think\Request;

class File {
    public function file($fileName) {
        $request = Request::instance();
        $referer = $request->header('referer');
        if (!$referer || strpos($referer, 'https://www.zhangbj.com') !== 0) {
            header("Status:403 Forbidden");
            return;
        }
        header('Content-type: application/octet-stream');
        header("Content-Disposition: attachment; filename=$fileName");
        header("X-Accel-Redirect:  /file/$fileName");
    }
}

参考

Nginx: X-Accel-Redirect

Nginx: XSendfile

Servers 相关文章推荐
教你快速开启Apache SkyWalking的自监控
Apr 25 Servers
nginx配置文件使用环境变量的操作方法
Jun 02 Servers
详解nginx进程锁的实现
Jun 14 Servers
制作能在nginx和IIS中使用的ssl证书
Jun 21 Servers
详解Nginx 被动检查服务器的存活状态
Oct 16 Servers
Nginx下SSL证书安装部署步骤介绍
Dec 06 Servers
docker 制作mysql镜像并自动安装
May 20 Servers
linux目录管理方法介绍
Jun 01 Servers
安装harbor作为docker镜像仓库的问题
Jun 14 Servers
nginx代理实现静态资源访问的示例代码
Jul 07 Servers
zabbix如何添加监控主机和自定义监控项
Aug 14 Servers
服务器nginx权限被拒绝解决案例
Sep 23 Servers
Nginx工作原理和优化总结。
利用Nginx代理如何解决前端跨域问题详析
Apr 02 #Servers
Nginx URL重写rewrite机制原理及使用实例
Apr 01 #Servers
nginx限制并发连接请求数的方法
Apr 01 #Servers
Nginx已编译的nginx-添加新模块
Nginx下配置Https证书详细过程
详解Nginx启动失败的几种错误处理
Apr 01 #Servers
You might like
php加密算法之实现可逆加密算法和解密分享
2014/01/21 PHP
WordPress分页伪静态加html后缀
2016/06/08 PHP
thinkPHP5.0框架URL访问方法详解
2017/03/18 PHP
PHP filesize函数用法浅析
2019/02/15 PHP
js程序中美元符号$是什么
2008/06/05 Javascript
zShowBox 图片放大展示jquery版 兼容性
2011/09/24 Javascript
js中哈希表的几种用法总结
2014/01/28 Javascript
jquery选择符快速提取web表单数据示例
2014/03/27 Javascript
jQuery模拟点击A标记示例参考
2014/04/17 Javascript
Javascript实现Web颜色值转换
2015/02/05 Javascript
JavaScript获得指定对象大小的方法
2015/07/01 Javascript
js实现跨域的几种方法汇总(图片ping、JSONP和CORS)
2015/10/25 Javascript
深入解析JavaScript编程中的this关键字使用
2015/11/09 Javascript
AngularJS实现元素显示和隐藏的几个案例
2015/12/09 Javascript
JS事件添加和移出的兼容写法示例
2016/06/20 Javascript
微信小程序通过api接口将json数据展现到小程序示例
2017/01/20 Javascript
vue复合组件实现注册表单功能
2017/11/06 Javascript
Node.js中,在cmd界面,进入退出Node.js运行环境的方法
2018/05/12 Javascript
微信小程序实现topBar底部选择栏效果
2018/07/20 Javascript
在Vue项目中用fullcalendar制作日程表的示例代码
2019/08/04 Javascript
element-ui树形控件后台返回的数据+生成组织树的工具类
2020/03/05 Javascript
0基础学习前端开发的一些建议
2020/07/14 Javascript
python 布尔操作实现代码
2013/03/23 Python
用Python的Django框架编写从Google Adsense中获得报表的应用
2015/04/17 Python
python表格存取的方法
2018/03/07 Python
基于YUV 数据格式详解及python实现方式
2019/12/09 Python
Python如何使用内置库matplotlib绘制折线图
2020/02/24 Python
使用pycharm和pylint检查python代码规范操作
2020/06/09 Python
CSS3 仿微信聊天小气泡实例代码
2017/04/05 HTML / CSS
ROSEFIELD手表荷兰官方网上商店:北欧极简设计女士腕表品牌
2018/01/24 全球购物
护理专业的自荐信
2013/10/22 职场文书
2015年纪检监察工作总结
2015/04/08 职场文书
小学英语教学经验交流材料
2015/11/02 职场文书
哪类餐饮行业,最适合在高校创业?
2019/08/19 职场文书
python中的plt.cm.Paired用法说明
2021/05/31 Python
磁贴还没死, 微软Win11可修改注册表找回Win10开始菜单
2021/11/21 数码科技