生活随笔
收集整理的這篇文章主要介紹了
基于 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()?+"\"");??????????????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;?????????????@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()){????????????????????????????xAccelRedirectFile(file,?response);????????????}?else?{???????????????response.sendError(404);??????????}??????}????????protected?void?xAccelRedirectFile(ResourceFile?file,?HttpServletResponse?response)???????????throws?IOException?{??????????String?encoding?=?response.getCharacterEncoding();????????????response.setHeader("Content-Type",?"application/octet-stream");????????????????????????????????????????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 也是可以的
????}????????????????????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 进行文件下载的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。