Skip to content

Instantly share code, notes, and snippets.

@DominikMostek
Last active August 29, 2015 14:02
Show Gist options
  • Save DominikMostek/aa661c5c5120cc25171e to your computer and use it in GitHub Desktop.
Save DominikMostek/aa661c5c5120cc25171e to your computer and use it in GitHub Desktop.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface FileUpload {
}
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
public class FileUploadReturnValueHandler implements HandlerMethodReturnValueHandler {
public static final String MSIE_USER_AGENT_IDENTIFIER = "MSIE";
public static final String USER_AGENT_HEADER = "user-agent";
public static final String REQUESTED_WITH = "X-Requested-With";
public static final String AJAX_IDENTIFIER = "XMLHttpRequest";
private final HandlerMethodReturnValueHandler delegate;
public FileUploadReturnValueHandler(HandlerMethodReturnValueHandler delegate) {
this.delegate = delegate;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
if (returnType.getMethodAnnotation(FileUpload.class) != null) {
return true;
} else {
return delegate.supportsReturnType(returnType);
}
}
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws Exception {
if (returnType.getMethodAnnotation(FileUpload.class) != null) {
HttpHeaders httpHeaders = new HttpHeaders();
browserSpecificActions(webRequest, httpHeaders);
returnValue = new ResponseEntity(
returnValue,
httpHeaders,
HttpStatus.OK
);
}
delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
private void browserSpecificActions(NativeWebRequest webRequest, HttpHeaders httpHeaders) {
String header = webRequest.getHeader(USER_AGENT_HEADER);
if (isInternetExplorer(header) && !isAjax(webRequest)) {
// IE downloads JSON as a file if its not requested with ajax.
// If we set text/plain mime type it is shown as a text in a browser
httpHeaders.setContentType(MediaType.TEXT_PLAIN);
}
}
private boolean isInternetExplorer(String header) {
return header.indexOf(MSIE_USER_AGENT_IDENTIFIER) != -1;
}
private boolean isAjax(NativeWebRequest webRequest) {
return AJAX_IDENTIFIER.equalsIgnoreCase(webRequest.getHeader(REQUESTED_WITH));
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import java.util.List;
@Component
public class FileUploadSupportFactoryBean implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(FileUploadSupportFactoryBean.class);
@Autowired
private RequestMappingHandlerAdapter adapter;
@Override
public void afterPropertiesSet() throws Exception {
List<HandlerMethodReturnValueHandler> handlers = Lists.newArrayList(adapter.getReturnValueHandlers());
decorateHandlers(handlers);
adapter.setReturnValueHandlers(handlers);
}
private void decorateHandlers(List<HandlerMethodReturnValueHandler> handlers) {
for (HandlerMethodReturnValueHandler handler : handlers) {
if (handler instanceof HttpEntityMethodProcessor) {
FileUploadReturnValueHandler decorator = new FileUploadReturnValueHandler(handler);
int index = handlers.indexOf(handler);
handlers.set(index, decorator);
logger.info("HttpEntityMethodProcessor was decorated with FileUploadReturnValueHandler");
break;
}
}
}
}
@RestController
public class ImportController
@RequestMapping(value = "/api/import", method = RequestMethod.POST, produces = "application/json")
public CustomResponse<ImportResult> importData(@RequestParam(value = "file") final MultipartFile file, Parameters parameters) {
// some processing
return new CustomResponse(data);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment