programing

Spring Boot 컨트롤러에서 이미지를 반환하고 파일 시스템처럼 사용하는 방법

powerit 2023. 10. 30. 21:19
반응형

Spring Boot 컨트롤러에서 이미지를 반환하고 파일 시스템처럼 사용하는 방법

스택 오버플로우에서 제공하는 다양한 방법을 시도해 보았는데, 뭔가를 놓친 것 같습니다.

현재 다음과 같은 이미지가 표시되는 Android 클라이언트(코드를 변경할 수 없음)가 있습니다.

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();

어디에url이미지의 위치(CDN의 정적 리소스)입니다.이제 내 Spring Boot API Endpoint는 동일한 코드가 API(Spring boot version 1.3.3)에서 이미지를 가져올 수 있도록 동일한 방식으로 파일 리소스처럼 동작해야 합니다.

그래서 나는 이것을 가지고 있습니다.

@ResponseBody
@RequestMapping(value = "/Image/{id:.+}", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE, produces = MediaType.IMAGE_JPEG_VALUE)
public ResponseEntity<byte[]> getImage(@PathVariable("id")String id) {
    byte[] image = imageService.getImage(id);  //this just gets the data from a database
    return ResponseEntity.ok(image);
}

Android 코드가 다음을 시도할 때http://someurl/image1.jpg로그에 다음과 같은 오류가 발생합니다.

처리기 [public organ.springframework.http]의 예외를 해결하는 중입니다.ResponseEntity com. my project.MyController.getImage(java.lang).String)]: org.springframework.web.HttpMediaType 허용 안 됨예외:허용 가능한 표현을 찾을 수 없습니다.

플러그를 꽂을 때도 동일한 오류가 발생합니다.http://someurl/image1.jpg브라우저로 이동합니다.

이상하게도 내 시험은 확인할 수 있습니다.

Response response = given()
            .pathParam("id", "image1.jpg")
            .when()
            .get("MyController/Image/{id}");

assertEquals(HttpStatus.OK.value(), response.getStatusCode());
byte[] array = response.asByteArray(); //byte array is identical to test image

일반적인 방식으로 이미지가 제공되는 것처럼 동작하도록 하려면 어떻게 해야 합니까? (안드로이드 코드가 보내는 내용 유형 헤더는 변경할 수 없습니다)

편집

코멘트 뒤 코드(내용유형설정, 테이크아웃)produces):

@RequestMapping(value = "/Image/{id:.+}", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE)
public ResponseEntity<byte[]> getImage(@PathVariable("id")String id, HttpServletResponse response) {
    byte[] image = imageService.getImage(id);  //this just gets the data from a database
    response.setContentType(MediaType.IMAGE_JPEG_VALUE);
    return ResponseEntity.ok(image);
}

브라우저에서 이것은 문자열화된 정크를 제공하는 것처럼 보입니다.안드로이드에서는 에러가 나지 않지만 이미지가 나타나지 않습니다.

저는 이것이 효과가 있을 거라 믿습니다.

@RequestMapping(value = "/Image/{id:.+}", method = RequestMethod.GET)
public ResponseEntity<byte[]> getImage(@PathVariable("id") String id) {
    byte[] image = imageService.getImage(id);
    return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(image);
}

컨텐츠 유형이 다음에 대해 설정되어 있음을 유의하십시오.ResponseEntity, 을 위한 것이 아닌HttpServletResponse직접적으로.

드디어 이걸 고쳤네요...나는 추가해야 했습니다.ByteArrayHttpMessageConverter나에게WebMvcConfigurerAdapter하위 클래스:

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    final ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
    final List<MediaType> list = new ArrayList<>();
    list.add(MediaType.IMAGE_JPEG);
    list.add(MediaType.APPLICATION_OCTET_STREAM);
    arrayHttpMessageConverter.setSupportedMediaTypes(list);
    converters.add(arrayHttpMessageConverter);

    super.configureMessageConverters(converters);
}

파일/마임 유형을 모르는 경우 이 작업을 수행할 수 있습니다.업로드된 파일을 가져다가 guid로 파일 이름을 바꾸고 확장자가 없으며 브라우저/스마트폰이 이미지를 로드할 수 있는 문제가 없는 경우에 이 작업을 수행했습니다.두번째는 다운로드 받을 파일을 제공하는 것입니다.

@RestController
@RequestMapping("img")
public class ImageController {

@GetMapping("showme")
public ResponseEntity<byte[]> getImage() throws IOException{
    File img = new File("src/main/resources/static/test.jpg");
    return ResponseEntity.ok().contentType(MediaType.valueOf(FileTypeMap.getDefaultFileTypeMap().getContentType(img))).body(Files.readAllBytes(img.toPath()));
}
@GetMapping("thing")
public ResponseEntity<byte[]> what() throws IOException{
    File file = new File("src/main/resources/static/thing.pdf");
    return ResponseEntity.ok()
            .header("Content-Disposition", "attachment; filename=" +file.getName())
            .contentType(MediaType.valueOf(FileTypeMap.getDefaultFileTypeMap().getContentType(file)))
            .body(Files.readAllBytes(file.toPath()));
}


}   

추가해야 하는 java 9+ 업데이트compile 'com.sun.activation:javax.activation:1.2.0'이것 또한 jakarta에 의해 옮겨졌거나 픽업되었습니다. 이 게시물을 보세요.

Apache Commons(아파치 커먼즈)를 사용하여 엔드포인트에서 이미지를 노출할 수 있습니다.

@RequestMapping(value = "/image/{imageid}",method= RequestMethod.GET,produces = MediaType.IMAGE_JPEG_VALUE)
public @ResponseBody byte[] getImageWithMediaType(@PathVariable int imageid) throws IOException {
    InputStream in = new ByteArrayInputStream(getImage(imageid));
    return IOUtils.toByteArray(in);
    }

모든 이미지가 엔드포인트에서 제공됩니다./image/{imageid}

언급URL : https://stackoverflow.com/questions/40557637/how-to-return-an-image-in-spring-boot-controller-and-serve-like-a-file-system

반응형