2017-02-13 48 views
0

我正在面臨Spring mvc下載包含名稱中包含空格的文件的問題。 我想要做的是使用內置的Spring MVC資源解析器從遠程主機下載文件。彈簧mvc - 文件名下載空白時出錯

我使用Spring安全以及Spring MVC的,但測試沒有具體的模式應用任何安全

春季安全配置:

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

然後請求到達MVC調度器,其中配置資源解析器等:

Spr荷蘭國際集團MVC配置:

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

的配置工作只是罰款不具有名稱空間中的文件。在Spring模塊上啓用調試日誌我發現這兩個請求(在文件名中有或沒有空格)都以完全相同的方式處理。 解決這兩個調用時,在Spring調度程序servlet的日誌之下。

第一次測試路徑:/測試下載/ 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=[[email protected]6eb843]]] 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

第二測試路徑:/測試下載/測試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=[[email protected]6eb843]]] 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

任何想法,爲什麼發生這種情況?

UPDATE

弗雷德裏克提示後,我配置了我使用測試遠程主機管理UTF-8 tomcat的,我發現,當它處理從春天來的請求,則返回505。

簡單的調用從瀏覽器到遠程主機:

「GET /test/test%20file.txt HTTP/1.1」,通過春收到200 15

電話:

「HEAD/test/test file.txt HTTP/1.1」505 -

我甚至在配置連接器之前嘗試在名稱中創建帶有%20的文件,並且它不起作用,因此可能甚至在編碼工作之前。

回答

0

該問題已通過創建自定義資源處理程序解決。

我們在細節所做的是建立在啓動時加載的配置

@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); 
    } 
} 

的更換是不是最完美的解決方案:)大概但我們現在簡單的需求就足夠了。

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字符集過濾器?

+0

您如何在瀏覽器中顯示網址?也許你可以嘗試編碼URL,然後在瀏覽器中顯示它:'java.net.URLEncoder.encode(url,「UTF-8」)' –

+1

這裏的問題似乎是在URL從Spring Security層解碼之後不被資源處理程序重新編碼。調試默認資源處理程序(在您發佈的類中使用),不會重新編碼空格。在調試中,我用%20覆蓋了運行時的值(感謝eclipse),並且發現文件沒有問題。所以我認爲現在唯一的解決方案是擴展默認的資源處理程序添加到解析器「特定路徑」/ test download/**的「重新編碼」步驟。 – Stefano