파일을 업로드 하는 것은 언제해도 헷갈린다. 방법도 여러 방법이 존재하는 듯 하고. 이 포스팅은 html2canvas로 변환한 이미지를 서버에 저장하는 기능을 구현하며 수행했던 작업을 기준으로 작성되었으며 자세한 설명은 생략되어있다(아직 공부부족)
(딱히 이미지업로드에만 해당되는 내용은 아니다)
먼저, 클라이언트로 부터 MultipartFile의 형태로 파일을 받아왔다는 것을 가정한다. 같은 기능을 구현하는 두가지 코드를 작성하였다.
변경 전
String sourceFileName = multifile.getOriginalFilename();
String sourceFileNameExtension = FilenameUtils.getExtension( sourceFileName).toLowerCase();
String destinationFileName = "thumbnail_" + dashboardid + "." + sourceFileNameExtension;
File destinationFile = new File( thumbnailPath + destinationFileName);
try {
if( !destinationFile.exists()) {
multifile.transferTo( destinationFile);
} catch ( Exception e) {
e.printStackTrace();
throw new PuzzleException( "err", e.getMessage());
}
변경 후
String thumbnailPath = STORAGE_PATH + "/dashboard_thumb/";
int dashboardid = thumbnail.getDashboardid();
MultipartFile multifile = thumbnail.getThumbnailImg();
try {
byte[] bytes = multifile.getBytes();
String fileName = "thumbnail_" + dashboardid + ".png";
Path path = Paths.get( thumbnailPath + fileName);
Files.write(path, bytes);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
사실 두 방법간에 큰 차이는 없는 것 같다.
서버에 저장된 이미지를 불러올 떄, 화면이 전환됨과 동시에 모든 파일을 불러와 렌더링하게 되면 화면이 전환되는 속도가 현저히 느려진다. 따라서 화면에 이미지를 불러줄 때는 비동기형태로 로딩해 렌더링하는 것이 바람직하다.
<img class="block-thumbnail-img" ng-src="/app/dashboard/thumbnail/{{item.DASHBOARDID}}" onerror="this.src = 'images/no_thumbnail.png';">
이처럼 img 태그의 src에 위와같이 경로설정을 해주면, 이 또한 하나의 RequestMapping된 경로로써 Spring Controller에 요청을 보낼 수 있게 된다.
@RequestMapping( value= "/dashboard/thumbnail/{dashboardid}", method=RequestMethod.GET)
public @ResponseBody byte[] getThumbnail( @PathVariable( "dashboardid") int dashboardid) {
return dashboardService.getThumbnail(dashboardid);
}
이렇게 위와 같이 설정을 하게 되면, 각각의 img태그마다 요청이 비동기로 진행이 된다.
이후 service에서 다음과 같이 코드를 설정하면, 각각의 이미지 파일을 빠르게 로드할 수 있다.
public byte[] getThumbnail( int dashboardid) {
String thumbnailPath = STORAGE_PATH + "/dashboard_thumb/";
Thumbnail thumbnail = thumbnailDao.findOne( dashboardid);
if( thumbnail == null) return null;
String filename = thumbnail.getFileName();
byte[] rtn = null;
InputStream in = null;
ByteArrayOutputStream bao = null;
BufferedImage bi = null;
try {
in = Files.newInputStream( Paths.get( thumbnailPath + filename));
bao = new ByteArrayOutputStream();
bi = ImageIO.read( in);
ImageIO.write( bi, "png", bao);
rtn = bao.toByteArray();
} catch ( Exception e) {
e.printStackTrace();
} finally {
try {
bao.close();
in.close();
} catch ( Exception e) {
e.printStackTrace();
}
}
return rtn;
}