MESSAGE
:
Request processing failed; nested exception is com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost :9090/uploads/91e5118e60924b21bd48a9ed19ab91ff_girl8.jpg returned a response status of 405 Method Not Allowed
Description
:
The server encountered an unexpected condition that prevented it from fulfilling the request.
Exception
:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is com.sun.jersey.api.client.UniformInterfaceException: PUT http://localhost:9090/uploads/91e5118e60924b21bd48a9ed19ab91ff/_girl8.jpg returned a response status of 405 Method Not Allowed org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:986) org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881) javax.servlet.http.HttpServlet.service(HttpServlet.java:660) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855) javax.servlet.http.HttpServlet.service(HttpServlet.java:741) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
使用的IDE: IDEA 2019-02
充当上传文件的Project hierarchy(Client):
接收文件的Project hierarchy(Server):
controller
/** * 跨服务器文件上传 * @return success */ @RequestMapping("/fileupload3") public String fileupload3(MultipartFile upload) throws Exception { System.out.println("service id doing..."); // 定义上传文件服务器路径 String path = "http://localhost:9090/uploads/"; // 说明上传文件项 // 获取上传文件的名称 String filename = upload.getOriginalFilename(); // 把文件的名称设置唯一值,uuid String uuid = UUID.randomUUID().toString().replace("-", ""); filename = uuid+"_"+filename; // 创建客户端的对象 Client client = Client.create(); // 和图片服务器进行连接 WebResource webResource = client.resource(path+filename); // 上传文件 webResource.put(upload.getBytes()); return "success"; }
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>文件上传</title> </head> <body> <form action="user/fileupload1" method="post" enctype="multipart/form-data"> 传统方式的文件上传:<input type="file" name="upload"> <br> <input type="submit" value="上载"> </form> <hr> <form action="user/fileupload2" method="post" enctype="multipart/form-data"> SpringMVC方式的文件上传:<input type="file" name="upload"> <br> <input type="submit" value="上载"> </form> <hr> <form action="user/fileupload3" method="post" enctype="multipart/form-data"> 跨服务器的文件上传:<input type="file" name="upload"> <br> <input type="submit" value="上载"> </form> </body> </html>
从 "1.出错的信息描述" 可以知道我们的错误在于 PUT请求被用于接收文件的TOMCAT拒绝 了。
请查看 Apache Tomcat 9 (9.0.30) - Default Servlet Reference 。我们需要注意到以下信息:
So by default, the default servlet is loaded at webapp startup and directory listings are disabled and debugging is turned off.
以下为 readonly
property的描述
Is this context "read only", so HTTP commands like PUT and DELETE are rejected? [true]
这意味着接收文件的TOMCAT默认加载DefaultServlet后,默认拒绝接收PUT和DELETE请求。因此我们需要 改变initParameters中的readonly = false 。
关于为什么readonly默认为true这一点,你可以先看看TOMCAT对于把readonly设置为false持有什么样的看法,以下为参考链接:
Apache Tomcat RCE if readonly set to false (CVE-2017-12617) - Alphabot Securityreadonly
set to
false
or the WebDAV servlet is enabled with the parameter
readonly
set to
false
. This configuration would allow any unauthenticated user to upload files (as used in WebDAV). It was discovered that the filter that prevents the uploading of JavaServer Pages (.jsp) can be circumvented. So JSPs can be uploaded, which then can be executed on the server.
Now since this feature is typically not wanted, most publicly exposed system won’t have readonly
set to false
.
不难推断出TOMCAT考虑到安全性,默认关闭了TOMCAT的PUT和DELETE请求(即readonly = true)。
根据 "4.出错分析" 可以知道我们需要修改web.xml文件的readonly参数。
我们需要在DefaultServlet的init-param中添加readonly为false(如果你的配置文件没有readonly,那么你需要手动添加readonly=false)
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>readonly</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
启动两个TOMCAT,现在展示效果
index.jsp(Client端):