나는 클라이언트에서 특정 url 로 이미지를 요청하면 이미지를 보내주는 방식을 만들고 싶었다.
Vue Axios 와 REST API, InputStream, URL.createObjectURL() 을(를) 이용하였다.
1. JAVA Spring Server
1) Controller
@GetMapping(path = "image/{imgId}/show")
public void getImageFileById(@PathVariable(name = "imgId") String imgId, HttpServletResponse response) throws IOException {
service.getImageFileById(imgId, response);
}
요청 받을 url path 설정해주고, url에 따라서 @PathVariable 을 받아주면 된다.
나는 ID 값을 받아서 사용할거라 ID만 받았다.
2) Service
public void getImageFileById(String imgId, HttpServletResponse response) throws IOException {
AttachFile file = fileQuery.getAttachFileList(imgId);
if (file != null) {
String atcFileOid = file.getAtcOid();
String filePath = prop.getUploadDir() + file.getFileRestoNm();
try (InputStream inputStream = new FileInputStream(filePath)) {
IOUtils.copy(inputStream, response.getOutputStream());
response.setContentType(MediaType.IMAGE_JPEG_VALUE); // 이미지 타입에 따라 변경
response.setHeader("Content-Disposition", "inline; filename=" + "/" + atcFileOid);
} catch (IOException e) {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
e.printStackTrace();
}
} else {
response.setStatus(HttpStatus.NOT_FOUND.value());
}
}
DB상에 존재하는 해당 파일 정보를 InputStream으로 읽어오고,
response.getOutputStream() 을 통해 내보낸다.
response.setContentType()은 전달할 이미지 타입을 설정,
response.setHeader()는 header 값을 설정한다.
사실 response 는 Controller 에서 처리했어야 하는데 귀찮아서 service에서 몰아서 끝냈다.
이렇게 하면 안 좋다. (추후 수정할 예정)
2. Vue.js Client
const loadImage = async (imgId) => {
const imageUrl = await getImageUrl(imgId);
image.value.url = imageUrl;
};
const getImageUrl = async (imgId) => {
try {
const response =
await $axios
.get(util.format(....getImageFileById, imgId), {
responseType: 'arraybuffer',
});
const blob = new Blob([response.data], { type: response.headers['content-type'] });
const imageUrl = URL.createObjectURL(blob);
return imageUrl;
} catch (err) {
console.error(err);
return null;
}
};
loadImage() 를 호출하면 axios 를 통해 서버로 이미지를 요청한다.
전달 받은 response 를 blob 형태로 변환한다.
Blob 이란?
javascript에서 이미지, 사운드, 비디오 같은 멀티 데이터를 다룰 때 사용한다.
blob 형태로 변환한 데이터를 URL.createObjectUrl() 로 url을 생성해준다.
URL.createObjectURL() 메소드는 주어진 객체를 가리키는 URL을 DOMString으로 변환하는 기능을 한다.
해당 url은 window 창이 사라지면 함께 사라지고, 다른 window에서 재사용이 불가능하다.
한 마디로 미리보기에 사용하기 적합하다. 호출 시 마다 새로운 url이 생성된다.
호출하면 우측 사진처럼 미리보기가 나온다.
+
서버에서 Response를 Controller로 옮겨서 소스를 수정했다.
1) Controller
@GetMapping(path = "image/{imgId}/show")
public void getImageFileById(@PathVariable(name = "imgId") String imgId, HttpServletResponse response) throws IOException {
InputStream inputStream = service.getImageFileById(imgId);
if(inputStream != null) {
String atcFileOid = service.getAtcFileOid(imgId);
IOUtils.copy(inputStream, response.getOutputStream());
response.setContentType(MediaType.IMAGE_JPEG_VALUE); // 이미지 타입에 따라 변경
response.setHeader("Content-Disposition", "inline; filename=" + "/" + atcFileOid);
}else {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
}
2) Service
public InputStream getImageFileById(String imgId) throws IOException {
AttachFile file = fileQuery.getAttachFileList(imgId);
if (file != null) {
String filePath = prop.getUploadDir() + file.getFileRestoNm();
return new FileInputStream(filePath);
}else {
return null;
}
}
서비스에서 필요한 정보를 제공하는 역할과 컨트롤러에서 응답을 처리하는 역할이 분리되어야,
코드의 가독성이 향상된다고 생각한다.
아직 부족하지만 조금이나마 깔끔한 코드를 짜려고 노력중이다.
'JAVA > Spring' 카테고리의 다른 글
[JAVA] find image file size - File 이미지 크기(가로X세로) 구하기 (0) | 2024.01.10 |
---|---|
[Spring] boot 에서 JWT 인증 토큰 생성 및 사용하기 (0) | 2023.12.01 |
[Spring] Multi module - 모듈 별 application.yml 파일 환경 설정 및 관리하는 방법 (0) | 2023.12.01 |
[JAVA] [Eclipse] project에 Dynamic Web Module 추가하는 방법 (Deployment Assembly) (0) | 2023.11.16 |
[JAVA] Map으로 전달 받은 JsonData List 목록(값) 추출하기 (0) | 2023.11.16 |