コントローラーに次のイメージダウンロード方法があります(Spring 4.1):
_@RequestMapping(value = "/get/image/{id}/{fileName}", method=RequestMethod.GET)
public @ResponseBody byte[] showImageOnId(@PathVariable("id") String id, @PathVariable("fileName") String fileName) {
setContentType(fileName); //sets contenttype based on extention of file
return getImage(id, fileName);
}
_
次のControllerAdvice
メソッドは、存在しないファイルを処理し、jsonエラー応答を返す必要があります。
_@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public @ResponseBody Map<String, String> handleResourceNotFoundException(ResourceNotFoundException e) {
Map<String, String> errorMap = new HashMap<String, String>();
errorMap.put("error", e.getMessage());
return errorMap;
}
_
私のJUnitテストは問題なく動作します
([〜#〜] edit [〜#〜]これは、拡張子.blaによるものです:これはappserverでも機能します):
_@Test
public void testResourceNotFound() throws Exception {
String fileName = "bla.bla";
mvc.perform(MockMvcRequestBuilders.get("/get/image/bla/" + fileName)
.with(httpBasic("test", "test")))
.andDo(print())
.andExpect(jsonPath("$error").value(Matchers.startsWith("Resource not found")))
.andExpect(status().is(404));
}
_
次の出力が得られます。
_MockHttpServletResponse:
Status = 404
Error message = null
Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY], Content-Type=[application/json]}
Content type = application/json
Body = {"error":"Resource not found: bla/bla.bla"}
Forwarded URL = null
Redirected URL = null
Cookies = []
_
しかし、私のアプリサーバーでは、存在しないイメージをダウンロードしようとすると次のエラーメッセージが表示されます。
([〜#〜] edit [〜#〜]これは、拡張子.jpgによるものです。これは、.jpg拡張子によるJUnitテストでも失敗します):
ERROR org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Failed to invoke @ExceptionHandler method: public Java.util.Map<Java.lang.String, Java.lang.String> nl.krocket.ocr.web.controller.ExceptionController.handleResourceNotFoundException(nl.krocket.ocr.web.backing.ResourceNotFoundException) org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
次のように、mvc構成でメッセージコンバーターを構成しました。
_@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(mappingJackson2HttpMessageConverter());
converters.add(byteArrayHttpMessageConverter());
}
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//objectMapper.registerModule(new JSR310Module());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper);
converter.setSupportedMediaTypes(getJsonMediaTypes());
return converter;
}
@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
arrayHttpMessageConverter.setSupportedMediaTypes(getImageMediaTypes());
return arrayHttpMessageConverter;
}
_
何が欠けていますか?そして、なぜJUnitテストは機能するのですか?
Springが応答のメディアタイプを決定する方法を決定する必要があります。それにはいくつかの方法があります。
デフォルトでは、SpringはAccept
ヘッダーではなくextensionを参照します。この動作は、 WebMvcConfigurerAdapter
を拡張する_@Configuration
_クラスを実装する場合に変更できます(または、Spring 5.0では単に WebMvcConfigurer
を実装するため。そこで、 configureContentNegotiation(ContentNegotiationConfigurer configurer)
をオーバーライドし、 ContentNegotiationConfigurer
を必要に応じて設定できます。たとえば、
_ContentNegotiationConfigurer#favorParameter
ContentNegotiationConfigurer#favorPathExtension
_
両方をfalse
に設定すると、SpringはAccept
ヘッダーを調べます。クライアントは_Accept: image/*,application/json
_と言って両方を処理できるため、Springは画像またはエラーJSONのいずれかを返すことができるはずです。
詳細と例については、コンテンツネゴシエーションに関する このSpringチュートリアル を参照してください。
HTTP Acceptヘッダーに注意してください。たとえば、コントローラーが「application/octet-stream」(応答)を生成する場合、Acceptヘッダーは「application/json」(要求)であってはなりません。
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void download(HttpServletResponse response) {}