Notice
Recent Posts
Recent Comments
Link
반응형
이로
HTML IMG 태그에 경로없이 이미지 전송 (HttpServletResponse 사용) 본문
반응형
이슈사항
- HTML 에서 IMG 태그 안 SRC 에 이미지에 대한 경로를 노출하지 않고 이미지 파일을 노출시키고 싶다.
- 성능이 조금 떨어지더라도 보안이 중요하다.
구성
- springboot 2.2.6
- JSP, JQuery, JSTL
해결방안
- HttpServletResponse를 사용하여 response에 image파일을 담아 반환한다.
- 파일경로를 암호화, 복호화 하여 사용한다.
- 이미지파일을 base64로 읽어 ModelAndView 형태로 JSP에 전송하여 출력
HttpServletResponse사용하여 이미지 파일 전송 로직
- HTML <IMG SRC = ""/> 에서 SRC값으로 IMG파일을 받아올 URL 을 넣는다.
- 특정 DATA 를 가져오기 위해 GET 방식으로 DATA를 호출할 수 있도록 한다.
- Controller에서 image file에 대한 정보를 불러오기 위해 FileVO를, 클라이언트의 브라우저 확인을 위해 request를, response에 IMG 파일을 담아 전송하기 위해 response를 커맨드 객체로 선언하고 fileService의 getImgFile을 호출한다.
- Service에서 fileInfo에 있는 이미지 파일에 대한 정보를 가지고 이미지 파일의 상세정보를 호출한뒤, fileFullpath 와 file의 원본파일명으로 이미지 파일을 가져올 준비를 한다. 그 다음 response객체의 헤더에 이미지 파일에 대한 정보를 담아주고, stream 을 통해 이미지 파일을 전송한다.
코드
1. HTML
<img src="<c:url value='/image?imageId=${imageId}'/>">
2. 컨트롤러
@RequestMapping(value = "/image",method = RequestMethod.GET)
public void getImgFile(FileVO fileVO, HttpServletRequest request, HttpServletResponse response) throws Exception {
fileService.getImgFile(fileVO,request, response);
}
3. 서비스 (FileService.class)
public void getImgFile(FileVO fileVO, HttpServletRequest request, HttpServletResponse response) throws Exception {
fileVO = fileService.selectFileInfo(fileVO);
FileComponent.getImgFile(request, response, fileVO.getFileFullPath(), fileVO.getOriginName());
}
4. 파일을 Response 객체에 담는 로직
public static void getImgFile(HttpServletRequest request, HttpServletResponse response, String fullFilePath, String original) throws Exception {
File file = new File(fullFilePath);
if (!file.exists()) {
throw new FileNotFoundException(fullFilePath);
}
if (!file.isFile()) {
throw new FileNotFoundException(fullFilePath);
}
// original : 원본 파일명
String extend = original.split("\\.")[1];
original = original.replaceAll("\r", "").replaceAll("\n", "");
response.setContentType("image/"+extend);
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "0");
setDisposition(original, request, response);
BufferedInputStream fin = null;
BufferedOutputStream outs = null;
byte[] byteImgArray = new byte[(int) file.length()];
try {
fin = new BufferedInputStream(new FileInputStream(file));
outs = new BufferedOutputStream(response.getOutputStream());
int read = 0;
while ((read = fin.read(byteImgArray)) != -1) {
outs.write(byteImgArray, 0, read);
}
} finally {
fin.close();
outs.close();
}
}
/**
* Disposition 지정하기.
*
* @param filename 파일명
* @param request 브라우저의 종류를 얻어온다.
* @param response Disposition을 지정해 Header를 설정한다.
* @throws Exception Throwble Unhandled Exception
*/
private static void setDisposition(String filename, HttpServletRequest request, HttpServletResponse response) throws Exception {
String browser = getBrowser(request);
String dispositionPrefix = "attachment; filename=";
String encodedFilename = null;
if (browser.equals("MSIE")) {
encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
} else if (browser.equals("Trident")) { // IE11 문자열 깨짐 방지
encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
} else if (browser.equals("Firefox")) {
encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
} else if (browser.equals("Opera")) {
encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
} else if (browser.equals("Chrome")) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < filename.length(); i++) {
char c = filename.charAt(i);
if (c > '~') {
sb.append(URLEncoder.encode("" + c, "UTF-8"));
} else {
sb.append(c);
}
}
encodedFilename = sb.toString();
} else {
throw new IOException("Not supported browser");
}
response.setHeader("Content-Disposition", dispositionPrefix + encodedFilename);
if ("Opera".equals(browser)) {
response.setContentType("application/octet-stream;charset=UTF-8");
}
}
반응형
'컴퓨터 > 개발일기' 카테고리의 다른 글
201222 쓰레드 다중처리 (0) | 2020.12.22 |
---|
Comments