Nginx 使用 X-Accel-Redirect 實現靜態文件下載的統計、鑑權、防盜鏈、限速等

需求

  • 統計靜態文件的下載次數;
  • 判斷用戶是否有下載權限;
  • 根據用戶指定下載速度;
  • 根據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將允許適用於CometHTTP流式應用程序的無緩衝響應。將此設置爲yes將允許響應被緩存。默認yes

X-Accel-Expires

如果已傳輸過的文件被緩存下載,設置Nginx文件緩存過期時間,單位秒。默認不過期。

X-Accel-Charset

設置文件字符集,默認UTF-8

使用條件

  • 必須有Nginx作爲後端服務的代理;
  • 必須訪問Nginx的代理地址,直接訪問後端服務Nginx會報404
  • 可自行配置Content-Type來控制是下載(application/octet-stream)還是展示(image/jpeg等);

代碼實現

  1. Nginx監聽9876端口。
  2. Nginx代理後端服務的8080端口。
  3. 設置/testAccel路徑爲internal,指定具體文件存儲的磁盤位置。
  4. 後端服務接收到文件下載請求,處理業務邏輯後X-Accel-Redirect/testAccel路徑。
  5. Nginx收到後端返回信息中的X-Accel-Redirect請求頭,接管文件下載或顯示任務。
  6. 請求路徑:http://localhost:9876/file/download/1234.jpg。

Nginx配置:

        location / {
            #root   html;
            root   F:/web/;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }

        location /testAccel {
            internal;
            alias F:/web/testAccel/file;
        }
        
        
        location /file {
            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:8080;            
        }

Java代碼

注意fileName添加:.+,或者獲取不到文件後綴名。

    @GetMapping("/file/download/{fileName:.+}")
    public void download(HttpServletRequest request,
                         HttpServletResponse response,
                         @PathVariable("fileName") String fileName) {
        //統計
        //鑑權
        //判斷Referer
        String referer = request.getHeader("Referer");
        System.out.println(referer);

        String prefix = "/testAccel";
        // 在這之前進行一些必要的處理,比如鑑權,或者其它的處理邏輯。
        // 通過X-Accel-Redirect返回在nginx中的實際下載地址
        response.setHeader("X-Accel-Redirect", prefix + "/" + fileName);
        response.setHeader("X-Accel-Limit-Rate", "1024");//限速,單位字節,默認不限
        response.setHeader("X-Accel-Buffering", "yes");//是否使用Nginx緩存,默認yes
    }

如果直接訪問路徑:http://localhost:9876/testAccel/1234.jpg,就會報404錯誤

 

 

 

參考:

https://www.zhangbj.com/p/507.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章