Spring mvc - 用于下载文件名的空格错误

时间:2017-02-13 10:08:24

标签: spring spring-mvc

我遇到Spring mvc的问题,要下载名称中包含空格的文件。 我想要做的是使用资源解析器内置的Spring MVC从远程主机下载文件。

我使用Spring安全性和Spring MVC但是在没有对特定模式应用任何安全性的情况下进行测试

  

Spring Security配置:

    <http>
....
    <intercept-url pattern="/test download/**" access="permitAll" requires-channel="https"  />
...
</http>

然后请求到达MVC调度程序,在那里配置资源解析器:

  

Spring MVC配置:

<mvc:resources  mapping="/test download/**" location="http://localhost:10089/test/" />

配置适用于名称中没有空格的文件。在Spring模块上启用调试日志我看到两个请求(文件名中有或没有空格)都以相同的方式处理。 解析两个调用时,在Spring调度程序servlet的日志下面。

  

第一个测试路径:/ test download / file.txt

... after security filters ..
DEBUG org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'mvc-dispatcher' processing GET request for [/portal/test%20download/file.txt]
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /test download/file.txt
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Did not find handler method for [/test download/file.txt]
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /test download/file.txt
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Did not find handler method for [/test download/file.txt]
DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Matching patterns for request [/test download/file.txt] are [/test download/**]
DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - URI Template variables for request [/test download/file.txt] are {}
DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapping [/test download/file.txt] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[URL [http://localhost:10089/test/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@2a6eb843]]] and 1 interceptor
DEBUG org.springframework.web.servlet.DispatcherServlet - Last-Modified value for [/portal/test%20download/file.txt] is: -1
DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
DEBUG org.springframework.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'mvc-dispatcher': assuming HandlerAdapter completed request handling
DEBUG org.springframework.web.servlet.DispatcherServlet - Successfully completed request
DEBUG org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normally
DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
  

结果:Content of the file is shown in the browser as expected

     

第二个测试路径:/ test download / test file.txt

... after security filters ..
DEBUG org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'mvc-dispatcher' processing GET request for [/portal/test%20download/test%20file.txt]
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /test download/test file.txt
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Did not find handler method for [/test download/test file.txt]
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /test download/test file.txt
DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Did not find handler method for [/test download/test file.txt]
DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Matching patterns for request [/test download/test file.txt] are [/test download/**]
DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - URI Template variables for request [/test download/test file.txt] are {}
DEBUG org.springframework.web.servlet.handler.SimpleUrlHandlerMapping - Mapping [/test download/test file.txt] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[URL [http://localhost:10089/test/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@2a6eb843]]] and 1 interceptor
DEBUG org.springframework.web.servlet.DispatcherServlet - Last-Modified value for [/portal/test%20download/test%20file.txt] is: -1
DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
DEBUG org.springframework.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'mvc-dispatcher': assuming HandlerAdapter completed request handling
DEBUG org.springframework.web.servlet.DispatcherServlet - Successfully completed request
DEBUG org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normally
DEBUG org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
  

结果:Http 404 is returned

这2个文件位于主机的同一个文件夹中,我使用本地服务器测试文件和具有相同结果的远程服务器。

我试图仅使用Spring配置来解决我的需求,因为我需要的基本上类似于代理,但是应用了安全规则。

  

Spring MVC版本:4.1.6.RELEASE

     

Spring Security版本:3.2.5.RELEASE

知道为什么会这样吗?

更新

在Frederik提示之后,我将我用作测试的tomcat配置为管理utf-8的远程主机,并且我发现当它处理来自Spring的请求时它返回505.

从浏览器到远程主机的简单调用:

  

&#34; GET /test/test%20file.txt HTTP / 1.1&#34; 200 15

通过Spring收到的电话:

  

&#34; HEAD / test / test file.txt HTTP / 1.1&#34; 505 -

我确实尝试在配置连接器之前使用名称中的%20创建文件,但它不起作用,所以甚至可能在编码工作之前。

2 个答案:

答案 0 :(得分:1)

通过创建自定义资源处理程序解决了该问题。

我们在细节方面所做的是创建一个在启动时加载的类作为配置

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {


    /**
     *
     * Add ResourceResolver that fix the whitespace problem in filename url.
     * resources that needs this fix must be configured here instead of inside xml
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/test download/**")
                .addResourceLocations("http://localhost:10089/test/")
                .resourceChain(true)
                .addResolver(new CustomPathResourceResolver())
                ;
    }


}

CustomPathResourceResolver是

import org.springframework.core.io.Resource;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.resource.ResourceResolver;
import java.io.IOException;

public class CustomPathResourceResolver extends PathResourceResolver implements ResourceResolver {

    @Override
    protected Resource getResource(String resourcePath, Resource location) throws IOException {
        //fixes problems with whitespaces in url
        resourcePath = resourcePath.replace(" ","%20");
        return super.getResource(resourcePath, location);
    }
}

替换不是最优雅的解决方案:)可能但是因为我们的简单需求现在已经足够了。

答案 1 :(得分:0)

负责根据URL查找资源的处理程序使用HandlerMapping .PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE,它对应于您在映射中配置的/**值。

https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java#L407

我非常确定用于获取文件的路径包含转义字符。因此,它将查找名为test%20file.txt的文件。您可以通过在test download文件夹中添加具有该名称的文件来验证是否是这种情况。

Spring实际上解码了URL - 你可以检查你的tomcat /容器是否真的是UTF-8字符集过滤器?

相关问题