在平常我们实现文件下载通常是通过普通 read-write方式,如下代码所示。
@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中加入以下配置
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代码为:
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());
}
//如果存在中文文件名或中文路径需要对其进行编码成 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;
}
}
分享到:
相关推荐
大型电商项目实战1:Redis+Rest+Linux+Nginx+Spring+SpringMVC实现JAVA高并发秒杀系统,baidu链接,谢谢
### 分布式框架简介SSM组合+springmvc+mybatis+shiro+restful+bootstrap #### 一、基础知识与入门 本节主要介绍如何基于SSM(Spring、SpringMVC、MyBatis)框架搭建一个简单的Web应用程序,并实现一个HelloWorld...
1、基于vue+python+flask+uwsgi+nginx+mysql的外包项目网站项目源码.zip 2、该资源包括项目的全部源码,下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为...
Nginx++Keepalived+Tomcat负载均衡&动静分离配置 本文主要介绍了Nginx、Keepalived和Tomcat的负载均衡和动静分离配置,旨在帮助读者了解如何搭建高可用、高性能的Web应用系统。 一、环境准备 在开始配置之前,...
总的来说,Nginx+upload+lua的组合提供了一种高效、灵活的文件上传解决方案,可以满足各种规模的应用场景。通过这种技术栈,你可以更好地控制文件上传过程,优化性能,以及实现自定义的业务逻辑。
在配置过程中,文章详细介绍了安装 JDK、JBOSS、Nginx、VirtualBox 等软件,配置网络环境,上传文件到虚机,配置 JBOSS 应用服务器的 JDK 环境,配置 standalone 模式相关配置,配置 Nginx 等步骤。 文章还提供了...
后端文件包+nginx文件+配置文件
Nginx+Uwsgi+Django(python3)+Vue部署,一步步实现。网上找了N多篇文章都没成功,特意记录,以免其他同学踩坑
配置Nginx+Tomcat+Redis环境时,可能会用到各种依赖包,如编译工具、库文件、配置脚本等。这些包确保所有组件能够正常安装和运行。 综上,"Nginx+Tomcat+Redis"的架构为构建高可用、高性能的Web服务提供了坚实的...
基于nginx tcp负载均衡 + redis的集群聊天服务器,网络层使用muduo库搭建,数据库使用MySQL 基于nginx tcp负载均衡 + redis的集群聊天服务器,网络层使用muduo库搭建,数据库使用MySQL 基于nginx tcp负载均衡 + ...
`FastDFS`是一个开源的分布式文件系统,它对文件进行管理,包括文件存储、文件同步、文件访问(文件上传、文件下载)等功能,解决了大容量存储和负载均衡的问题。 【ActiveMQ】 `ActiveMQ`是Apache的开源消息中间件...
《构建基于Spring+SpringMVC+MyBatis的在线考试系统》 在信息化时代,教育领域不断探索新的教学模式,其中在线考试系统以其便捷、高效的特点受到广泛关注。本项目是利用Spring、SpringMVC和MyBatis三大主流框架构建...
部署时,系统可能运行在Tomcat或Jetty等应用服务器上,结合Nginx等反向代理服务器进行负载均衡和静态资源处理。 7. 测试与优化: 在系统上线前,会进行单元测试、集成测试和压力测试,确保系统功能的正确性和稳定...
在这个项目中,Spring和SpringMVC负责整体的控制和业务逻辑,Mybatis则作为数据访问层,与Oracle数据库进行交互。当需要提高数据读取速度或者减轻数据库负载时,Redis作为缓存层介入,存储热点数据。整个系统的设计...
1. 首先,确保你已经下载了"userDefineLang_nginx.xml"文件。 2. 打开Notepad++,点击菜单栏上的“语言”选项,选择“定义用户语言”。 3. 在弹出的窗口中,点击“导入”按钮,找到并选择之前下载的"userDefineLang_...
Java基于SSM(Spring+SpringMVC+MyBatis)的高校学生请假管理系统是一个典型的Web应用项目,它利用了Spring框架来管理应用的组件和依赖,SpringMVC作为控制器处理HTTP请求,而MyBatis则作为持久层框架,负责数据库...
本项目——"Movies电影推荐Spring+SpringMVC+Mybatis",就是这样一个完整的前后端解决方案,利用了Java开发中的三大主流框架——Spring、SpringMVC和Mybatis,实现了高效且灵活的电影推荐功能。 首先,Spring框架是...
示例:使用Docker搭建基于Nginx+Tomcat的分布式部署架构。
这个小例子"nginx+tomcat+redis完成session共享"旨在演示如何通过这三种技术实现跨服务器的用户会话共享,以提升用户体验并简化系统管理。以下是这些技术及其在会话共享中的作用: 1. **Nginx**:Nginx是一款高性能...