文件上传之跨服务器
# 100.文件上传之跨服务器
实现跨服务器上传
# 需求
在实际开发中,我们会有很多处理不同功能的服务器。例如:
- 应用服务器:负责部署我们的应用
- 数据库服务器:运行我们的数据库
- 缓存和消息服务器:负责处理大并发访问的缓存和消息
- 文件服务器:负责存储用户上传文件的服务器。(例如本博客就使用了第三方图床,其实也就是一个文件服务器)
分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。
# 环境准备
首先我们得有一个图片的服务器;其次得解决应用服务器如何将图片传过去。
这里我们使用 jersey-client 和 jersey-core 的依赖,这是 sub 公司提供的,可以实现传图片的问题。
# 搭建图片服务项目
新建一个模块:
修改 index.jsp
<html>
<body>
<h2>Hello File Server!</h2>
</body>
</html>
2
3
4
5
新建 webapp/uploads 文件夹,后续我们上传文件就在该目录下
同时,我们需要准备 2 个 Tomcat,可以在 IDEA 中新建一个配置。点击编辑配置:
然后在右上角点击加号--然后在列表中找到 Tomcat 服务器
然后我们给该启动配置,改个名;然后修改端口,不和另一个 Tomcat 冲突
然后我们点击修复-并选择 fileUploadServer: war
我们启动,可以看到能正常访问首页 index.jsp
# 新增表单
我们在应用服务器的项目里,新增一个表单:
<h3>跨服务器文件上传</h3>
<form action="/user/fileUpload3" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"/> <br/>
<input type="submit" value="上传"/>
</form>
2
3
4
5
# 引入依赖
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.1</version>
</dependency>
2
3
4
5
6
7
8
9
10
11
# 新增控制器方法
我们复制一份 fileUpload2 方法,并改下路径和方法名为 3:
@RequestMapping("/fileUpload3")
public String fileUpload3(HttpServletRequest request, MultipartFile upload) throws IOException {
System.out.println("fileUpload2");
String realPath = request.getSession().getServletContext().getRealPath("/uploads/");
System.out.println("realPath: " + realPath);
File file = new File(realPath);
if (! file.exists()) {
// 创建该文件夹
file.mkdirs();
}
String originalFilename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replace("-", "");// 防止文件名重复,这里我们将减号替换为空字符串
originalFilename = uuid + "_" + originalFilename;
upload.transferTo(new File(realPath, originalFilename));
return "success";
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
我们删除获取文件路径的代码:因为我们是跨服务器了,所以不用这个代码。
String realPath = request.getSession().getServletContext().getRealPath("/uploads/");
System.out.println("realPath: " + realPath);
File file = new File(realPath);
if (! file.exists()) {
// 创建该文件夹
file.mkdirs();
}
2
3
4
5
6
7
方法参数中的 HttpServletRequest request,
也可以删了。然后关于上传的部分也可以删了:
upload.transferTo(new File(realPath, originalFilename));
此时我们的方法如下:
@RequestMapping("/fileUpload3")
public String fileUpload3(HttpServletRequest request, MultipartFile upload) throws IOException {
System.out.println("fileUpload3");
String originalFilename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replace("-", "");// 防止文件名重复,这里我们将减号替换为空字符串
originalFilename = uuid + "_" + originalFilename;
return "success";
}
2
3
4
5
6
7
8
然后我们定义一个路径,表示要上传的文件的地址,这里我们以 fileUpload 项目的地址为例:
// 定义上传文件服务器的路径
String path = "http://localhost:9090/fileUploadServer_war/uploads/";
2
接下来我们要做的是:
- 创建客户端对象 Client
- 和图片服务器进行连接
- 上传图片
// 创建客户端对象
Client client = Client.create();
// 和文件服务器进行连接
WebResource resource = client.resource(path + originalFilename);
// 上传文件
resource.put(upload.getBytes());
2
3
4
5
6
7
8
# 重启并测试
然后我们重启,上传图片测试,可以看到 fileUploadServer 项目里能正常有图片
# 如果遇到报错
如果在上传图片后,遇到报错:
com.sun.jersey.api.client.UniformInterfaceException: ... returned a response status of 403
是因为 Tomcat 默认禁止上传,在 Tomcat 中的 config 中的 web.xml 中进行以下的配置就可以进行文件的上传了.
在 Tomcat 配置文件中 ( apache-tomcat-8.0.50\conf\web.xml)113 行左右,添加如下代码
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
2
3
4
添加后部分配置如下:
重启服务器即可。
# 源码
本项目已将源码上传到 GitHub (opens new window) 和 Gitee (opens new window) 上。并且创建了分支 demo9,读者可以通过切换分支来查看本文的示例代码。