I have files stored in MongoDB which can be uploaded/downloaded/deleted via a Rest service. I'd like to download files from MongoDB via Spring Integration (+Boot+Embedded Jetty) but I can't figure out how to set the Content-Disposition header properly because the downloaded file has the correct payload but the filename is wrong (it's receiveGateway without any extension):
xml config
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
<bean id="byteArrayHttpMessageConverter"
class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
</bean>
<int:channel id="http.frontend.rx"/>
<int:channel id="http.frontend.tx"/>
<int:channel id="http.backend.mysql.api.rx"/>
<int:channel id="http.backend.mysql.api.tx"/>
<int:channel id="http.backend.mongodb.api.rx"/>
<int:channel id="http.backend.mongodb.api.tx"/>
<!-- -->
<int-http:inbound-gateway
id="frontEndToFlow"
request-channel="http.frontend.rx"
reply-channel="http.frontend.tx"
path="/receiveGateway"
mapped-request-headers="*"
mapped-response-headers="Content-Disposition,Content-Length,Content-Type,Server,Application-Context,Content-Transfer-Encoding"
message-converters="byteArrayHttpMessageConverter"
supported-methods="GET,POST,PUT,DELETE"/>
<int-http:outbound-gateway
id="FlowToBackEnd"
request-channel="http.backend.mysql.api.tx"
reply-channel="http.backend.mysql.api.rx"
url="http://localhost:7070/api/{path}"
http-method-expression="headers.http_requestMethod"
expected-response-type="java.lang.String"
charset="UTF-8">
<int-http:uri-variable name="path" expression="'users/user@gmail.com/'"/>
</int-http:outbound-gateway>
<int-http:outbound-gateway
id="springFlowToHttpBackEndMongoDB"
request-channel="http.backend.mongodb.api.tx"
reply-channel="http.backend.mongodb.api.rx"
url="http://localhost:5050/api/{path}"
http-method-expression="headers.http_requestMethod"
message-converters="byteArrayHttpMessageConverter"
mapped-request-headers="*"
mapped-response-headers="Content-Disposition,Content-Length,Content-Type,Server,X-Application-Context,Content-Transfer-Encoding"
expected-response-type="byte[]"
charset="UTF-8">
<int-http:uri-variable name="path" expression="'download/53cffb7c6c29a4f718627905'"/>
</int-http:outbound-gateway>
<int:service-activator
id="inboundServiceActivator"
input-channel="http.frontend.rx"
output-channel="http.backend.mongodb.api.tx"
ref="messageReaderService"
method="printContent">
</int:service-activator>
<int:service-activator
id="outboundServiceActivator"
input-channel="http.backend.mongodb.api.rx"
output-channel="http.frontend.tx"
ref="messageReaderService"
method="printContent">
</int:service-activator>
http request/response headers
Remote Address:::1:8080
Request URL:http://localhost:8080/receiveGateway
Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,ro;q=0.6,nb;q=0.4
Connection:keep-alive
Cookie:m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D
DNT:1
Host:localhost:8080
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Response Headersview source
Content-Length:33331
Content-Type:application/octet-stream
Server:Jetty(8.1.15.v20140411)
X-Content-Disposition:attachment; filename="aqmAR47_460s.jpg"
Application.java
@Configuration
@ComponentScan
@EnableAutoConfiguration
@ImportResource("classpath:httpgateway.xml")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
MessageReaderService.java - used it to see headers ... which are correct ...
@Component
public class MessageReaderService {
public Message printContent(Message message){
System.out.println(message.getHeaders().toString());
return message;
}
}
System.out.println console output
{errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3, http_requestMethod=GET, Cookie=m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3, Host=localhost:8080, User-Agent=Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36, http_requestUrl=http://localhost:8080/receiveGateway, Connection=keep-alive, Accept-Language=en-US,en;q=0.8,ro;q=0.6,nb;q=0.4, Accept-Encoding=gzip,deflate,sdch, DNT=1, Accept=[text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8], id=a5c4630e-f064-7245-8c8d-9e6706c361af, timestamp=1406907105217}
2014-08-01 18:31:45.218 WARN 8364 --- [qtp699466412-13] o.s.i.h.support.DefaultHttpHeaderMapper : Header 'X-errorChannel' with value 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:45.218 WARN 8364 --- [qtp699466412-13] o.s.i.h.support.DefaultHttpHeaderMapper : Header 'X-replyChannel' with value 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:45.218 WARN 8364 --- [qtp699466412-13] o.s.i.h.support.DefaultHttpHeaderMapper : Header 'X-id' with value 'a5c4630e-f064-7245-8c8d-9e6706c361af' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:45.219 WARN 8364 --- [qtp699466412-13] o.s.i.h.support.DefaultHttpHeaderMapper : Header 'X-timestamp' with value '1406907105217' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
{errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3, http_requestMethod=GET, Cookie=m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@2f53f6f3, Host=localhost:8080, Content-Length=33331, User-Agent=Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36, http_requestUrl=http://localhost:8080/receiveGateway, Connection=keep-alive, Server=Jetty(8.1.15.v20140411), Accept-Language=en-US,en;q=0.8,ro;q=0.6,nb;q=0.4, Content-Disposition=attachment; filename="aqmAR47_460s.jpg", http_statusCode=200, Accept-Encoding=gzip,deflate,sdch, DNT=1, Content-Type=application/octet-stream, X-Application-Context=application:5050, Accept=[text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8], id=4c1f52c8-b5f7-067c-2d60-826242d9d2db, timestamp=1406907105236}
{errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8, http_requestMethod=GET, Cookie=m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8, Host=localhost:8080, User-Agent=Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36, http_requestUrl=http://localhost:8080/receiveGateway, Connection=keep-alive, Accept-Language=en-US,en;q=0.8,ro;q=0.6,nb;q=0.4, Accept-Encoding=gzip,deflate,sdch, DNT=1, Accept=[text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8], id=21994eda-55aa-c798-53bc-c406e53e878d, timestamp=1406907106040}
2014-08-01 18:31:46.041 WARN 8364 --- [qtp699466412-14] o.s.i.h.support.DefaultHttpHeaderMapper : Header 'X-errorChannel' with value 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:46.042 WARN 8364 --- [qtp699466412-14] o.s.i.h.support.DefaultHttpHeaderMapper : Header 'X-replyChannel' with value 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:46.043 WARN 8364 --- [qtp699466412-14] o.s.i.h.support.DefaultHttpHeaderMapper : Header 'X-id' with value '21994eda-55aa-c798-53bc-c406e53e878d' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
2014-08-01 18:31:46.043 WARN 8364 --- [qtp699466412-14] o.s.i.h.support.DefaultHttpHeaderMapper : Header 'X-timestamp' with value '1406907106040' will not be set since it is not a String and no Converter is available. Consider registering a Converter with ConversionService (e.g., <int:converter>)
{errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8, http_requestMethod=GET, Cookie=m=1933:86400%7C1800|2377:small|2491:chart|3247:t|34e2:|47ba:t|1d98:t|2a03:t|745a:t|77cb:t|5cf4:t|ca3:t|54e1:t|4e71:small|e69:chart|45b9:86400%7C1800|4a01:t|4c1b:t|3eff:t; JSESSIONID=8ACC161B9338DC122564C8BAB81EF25D, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@6105c7d8, Host=localhost:8080, Content-Length=33331, User-Agent=Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36, http_requestUrl=http://localhost:8080/receiveGateway, Connection=keep-alive, Server=Jetty(8.1.15.v20140411), Accept-Language=en-US,en;q=0.8,ro;q=0.6,nb;q=0.4, Content-Disposition=attachment; filename="aqmAR47_460s.jpg", http_statusCode=200, Accept-Encoding=gzip,deflate,sdch, DNT=1, Content-Type=application/octet-stream, X-Application-Context=application:5050, Accept=[text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8], id=a048606a-f03f-89d8-e981-bb661bc7e955, timestamp=1406907106058}
Good. I see now.
First of all: please, raise, an improvement JIRA issue (https://jira.spring.io/browse/INT):
Content-Disposition
is really a standard HTTP header and have to map it by default.Right now you can overcome it with injected
DefaultHttpHeaderMapper
instead of thosemapped-request-headers
andmapped-response-headers
. In addition you have to configuresetUserDefinedHeaderPrefix
asnull
.It is
X-
by default, so we should change it to populateContent-Disposition
.Thank you for pointing it out!