@RequestMapping(value = "/image-manual-response", method = RequestMethod.GET) public void getImageAsByteArray(HttpServletResponse response) throws IOException { InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); response.setContentType(MediaType.IMAGE_JPEG_VALUE); IOUtils.copy(in, response.getOutputStream()); }
و URL درخواست آن :
http://localhost:8080/spring-mvc-xml/image-manual-response.jpg
این مثال از IOUtils از کتابخانه org.apache.commons.io استفاده میکند.
همانطور که میشه دید این کد بصورت hardcode میباشد و انعطاف پذیری بسیاری کمی در مورد تغییرات آتی دارد
حال بیاییم مدلی منعطف تر داشته باشیم :
HttpMessageConverter :
ابتدا نیاز داریم که کلاس Controller@ ما ResponseBody@ را هم داشته باشد
و بعد نوع برگشتی متد کنترلر را بر اساس مدیا، قابل تغییر باشد که در اینجا از تبدیل کننده ByteArrayHttpMessageConverter استفاده میکنیم که دیتای آرایه byte یک عکس را به پیام مناسب آن تبدیل میکند
ByteArrayHttpMessageConverter به طور پیش فرض ثبت شده است اما برای ست کردن تنظیماتی نیاز داریم که سفارشی سازی کنیم
در ابتدا نیاز داریم که یک Bean جهت MessageConverter درون Spring MVC Context ثبت کنیم
ابتدا روش تنظیمات در XML را شرح میدهیم :
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>image/jpeg</value> <value>image/png</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
در تنظیمات بالا انواع Media Type های مورد نیاز را هم معرفی کردیم و این تنظیمات باعث میشود تصاویر به ByteArrayHttpMessageConverter جهت response body تبدیل شوند
اگر تنظیمات بالا در تگ <mvc:message-converters> ثبت نشوند از مبدل پیش فرض استفاده خواهد شد
تنظیمات بوسیله کد java :
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(byteArrayHttpMessageConverter()); } @Bean public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() { ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter(); arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes()); return arrayHttpMessageConverter; } private List<MediaType> getSupportedMediaTypes() { List<MediaType> list = new ArrayList<MediaType>(); list.add(MediaType.IMAGE_JPEG); list.add(MediaType.IMAGE_PNG); list.add(MediaType.APPLICATION_OCTET_STREAM); return list; }
حالا میتوانیم از آن در متد کنترلر استفاده کنیم :
@RequestMapping(value = "/image-byte-array", method = RequestMethod.GET) public @ResponseBody byte[] getImageAsByteArray() throws IOException { InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); return IOUtils.toByteArray(in); }
http://localhost:8080/spring-mvc-xml/image-byte-array.jpg
با این روش میتوانیم با انعطاف بیشتری محتوای یک تصویر را به []byte تبدیل کرده و ارسال کنیم ولی چون return type متد کنترلی []byte است نمیتوانیم دسترسی روی header و response status code داشته باشیم برای این منظور میتوانیم از ResponseEntity استفاده کنیم
ResponseEntity :
@RequestMapping(value = "/image-response-entity", method = RequestMethod.GET) public ResponseEntity<byte[]> getImageAsResponseEntity() { HttpHeaders headers = new HttpHeaders(); InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); byte[] media = IOUtils.toByteArray(in); headers.setCacheControl(CacheControl.noCache().getHeaderValue()); ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(media, headers, HttpStatus.OK); return responseEntity; }
با این نوع برگشتی میتوان روی header و response status code دسترسی داشت و باز انعطاف پذیری را بالاتر برد و مثلا زمانی که خطایی رخ داد status code لازم را ارسال کنیم
Resource Class :
از کلاس Resource میتوان برای local file, remote file, classpath resource استفاده کرد که در مورد استفاده کنونی میتوانیم محتوای یک تصویر را به یک Resource class برگردانیم برای این منظور باید حتما ResponseBody@ را استفاده کرده باشیم
@ResponseBody @RequestMapping(value = "/image-resource", method = RequestMethod.GET) public Resource getImageAsResource() { return new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg"); }
و اگر کنترل بیشتری نیاز باشد بدین صورت میتوانیم بنویسیم :
@RequestMapping(value = "/image-resource", method = RequestMethod.GET) @ResponseBody public ResponseEntity<Resource> getImageAsResource() { HttpHeaders headers = new HttpHeaders(); Resource resource = new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg"); return new ResponseEntity<>(resource, headers, HttpStatus.OK); }