日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

基于 Nginx XSendfile + SpringMVC 进行文件下载

發布時間:2025/5/22 javascript 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于 Nginx XSendfile + SpringMVC 进行文件下载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://denger.iteye.com/blog/1014066


基于 Nginx XSendfile + SpringMVC 進行文件下載


PS:經過實際測試,通過 nginx 提供文件下載功能的時候,在 Application Server(Java/RoR/Go...) 端不設置 Content-Length 也是可以的


在平常我們實現文件下載通常是通過普通 read-write方式,如下代碼所示。

Java代碼 ?
  • @RequestMapping("/courseware/{id}")???
  • public?void?download(@PathVariable("id")?String?courseID,?HttpServletResponse?response)?throws?Exception?{??
  • ??
  • ?????ResourceFile?file?=?coursewareService.downCoursewareFile(courseID);??
  • ?????response.setContentType(file.getType());??
  • ?????response.setContentLength(file.contentLength());??
  • ?????response.setHeader("Content-Disposition","attachment;?filename=\""?+?file.getFilename()?+"\"");??
  • ?????//Reade?File?-?>?Write?To?response??
  • ?????FileCopyUtils.copy(file.getFile(),?response.getOutputStream());??
  • ?}??

  • ??? 由于程序的IO都是調用系統底層IO進行文件操作,于是這種方式在read和write時系統都會進行兩次內存拷貝(共四次)。linux 中引入的 sendfile 的實際就為了更好的解決這個問題,從而實現"零拷貝",大大提升文件下載速度。
    ??? 使用 sendfile() 提升網絡文件發送性能
    ??? RoR網站如何利用lighttpd的X-sendfile功能提升文件下載性能
    ??

    ??? 在apache,nginx,lighttpd等web服務器當中,都有sendfile feature。下面就對 nginx 上的XSendfile與SpringMVC文件下載及訪問控制進行說明。我們這里的大體流程為:
    1.用戶發起下載課件請求; (http://dl.mydomain.com/download/courseware/1)
    ???? 2.nginx截獲到該(dl.mydomain.com)域名的請求;
    ???? 3.將其proxy_pass至應用服務器;
    ???? 4.應用服務器根據課件id獲取文件存儲路徑等其它一些業務邏輯(如增加下載次數等);
    ???? 5.如果允許下載,則應用服務器通過setHeader -> X-Accel-Redirect 將需要下載的文件轉發至nginx中);
    ???? 6.Nginx獲取到header以sendfile方式從NFS讀取文件并進行下載。

    ???? 其nginx中的配置為:
    ???? 在location中加入以下配置
    ????? Conf代碼 ?
  • server?{??
  • ????????listen?80;??
  • ????????server_name?dl.mydomain.com;??
  • ??
  • ????????location?/?{??
  • ????????????proxy_pass??http://127.0.0.1:8080/;??#首先pass到應用服務器??
  • ????????????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;??
  • ??
  • ????????????client_max_body_size???????10m;??
  • ????????????client_body_buffer_size????128k;??
  • ??
  • ????????????proxy_connect_timeout??????90;??
  • ????????????proxy_send_timeout?????????90;??
  • ????????????proxy_read_timeout?????????90;??
  • ??
  • ????????????proxy_buffer_size??????????4k;??
  • ????????????proxy_buffers??????????????4?32k;??
  • ????????????proxy_busy_buffers_size????64k;??
  • ????????????proxy_temp_file_write_size?64k;??
  • ??
  • ????????}??
  • ??
  • ????????location?/course/?{???
  • ????????????charset?utf-8;??
  • ????????????alias???????/nfs/files/;?#文件的根目錄(允許使用本地磁盤,NFS,NAS,NBD等)??
  • ????????????internal;??
  • ????????}??
  • ????}??


  • ??? 其Spring代碼為:
    ??? Java代碼 ?
  • package?com.xxxx.portal.web;??
  • ??
  • import?java.io.IOException;??
  • import?java.io.UnsupportedEncodingException;??
  • ??
  • import?javax.servlet.http.HttpServletResponse;??
  • ??
  • import?org.springframework.beans.factory.annotation.Autowired;??
  • import?org.springframework.stereotype.Controller;??
  • import?org.springframework.web.bind.annotation.PathVariable;??
  • import?org.springframework.web.bind.annotation.RequestMapping;??
  • ??
  • import?com.xxxx.core.io.ResourceFile;??
  • import?com.xxxx.portal.services.CoursewareService;??
  • ??
  • /**?
  • ?*?File?download?controller,?provide?courseware?download?or?other?files.?<br>?
  • ?*?<br>?
  • ?*?<i>?download?a?course?URL?e.g:<br>?
  • ?*?http://dl.mydomain.com/download/courseware/1?</i>?
  • ?*??
  • ?*?@author?denger?
  • ?*/??
  • @Controller??
  • @RequestMapping("/download/*")??
  • public?class?DownloadController?{??
  • ??
  • ????private?CoursewareService?coursewareService;??
  • ??????
  • ????protected?static?final?String?DEFAULT_FILE_ENCODING?=?"ISO-8859-1";??
  • ??
  • ????/**??
  • ?????*?Under?the?courseware?id?to?download?the?file.??
  • ?????*???
  • ?????*?@param?courseID?The?course?id.??
  • ?????*?@throws?IOException???
  • ?????*/??
  • ????@RequestMapping("/courseware/{id}")??
  • ????public?void?downCourseware(@PathVariable("id")?String?courseID,?final?HttpServletResponse?response)?throws?IOException?{??
  • ????????ResourceFile?file?=?coursewareService.downCoursewareFile(courseID);??
  • ????????if?(file?!=?null?&&?file.exists()){??
  • ????????????//?redirect?file?to?x-accel-Redirect???
  • ????????????xAccelRedirectFile(file,?response);??
  • ??
  • ????????}?else?{?//?If?not?found?resource?file,?send?the?404?code??
  • ????????????response.sendError(404);??
  • ????????}??
  • ????}??
  • ??
  • ????protected?void?xAccelRedirectFile(ResourceFile?file,?HttpServletResponse?response)???
  • ????????throws?IOException?{??
  • ????????String?encoding?=?response.getCharacterEncoding();??
  • ??
  • ????????response.setHeader("Content-Type",?"application/octet-stream");??
  • ????????//這里獲取到文件的相對路徑。其中?/course/?為虛擬路徑,主要用于nginx中進行攔截包含了/course/?的URL,?并進行文件下載。??
  • ????????//在以上nginx配置的第二個location?中同樣也設置了?/course/,實際的文件下載路徑并不會包含?/course/??
  • ????????//當然,如果希望包含的話可以將以上的?alias?改為?root?即可。??
  • ????????response.setHeader("X-Accel-Redirect",?"/course/"??
  • ????????????????+?toPathEncoding(encoding,?file.getRelativePath()));??
  • ????????response.setHeader("X-Accel-Charset",?"utf-8");??
  • ??
  • ????????response.setHeader("Content-Disposition",?"attachment;?filename="??
  • ????????????????+?toPathEncoding(encoding,?file.getFilename()));??
  • ??????? // response.setContentLength((int)?file.contentLength());? // 經過實際測試,這里不設置 Content-Length 也是可以的
  • ????}??
  • ??
  • ????//如果存在中文文件名或中文路徑需要對其進行編碼成?iSO-8859-1??
  • ????//否則會導致?nginx無法找到文件及彈出的文件下載框也會亂碼??
  • ????private?String?toPathEncoding(String?origEncoding,?String?fileName)?throws?UnsupportedEncodingException{??
  • ????????return?new?String(fileName.getBytes(origEncoding),?DEFAULT_FILE_ENCODING);??
  • ????}??
  • ??
  • ????@Autowired??
  • ????public?void?setCoursewareService(CoursewareService?coursewareService)?{??
  • ????????this.coursewareService?=?coursewareService;??
  • ????}??
  • }?

  • 轉載于:https://www.cnblogs.com/leonxyzh/p/7288991.html

    總結

    以上是生活随笔為你收集整理的基于 Nginx XSendfile + SpringMVC 进行文件下载的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。