이번 포스팅은 웹서버에 등록되어있는 파일을 다운로드 받아보기위한 코드를 구현하도록 해보겠습니다.
해당 다운로드 코드는 멀티브라우저 지원을합니다.
호환브라우저는 (IE,파이어폭스,오페라,크롬,사파리) 모두 지원이 되는 코드입니다
유틸성 코드는 다음과 같습니다.
public class DownUtil { public void download(HttpServletRequest request ,HttpServletResponse response ,String realfilepath ,String realfilename ,String originalfilename) { String defaultfilepath = request.getSession().getServletContext().getRealPath("/"); //해당 realfilepath 변수에 들어갈 파일경로는 "/경로1/경로2/ << 이런식으로 들어갈경우를 가정 //만약 경로1/경로2 이런식으로 줄경우 if문을 삭제 또는 주석처리 if(realfilepath.length() > 0) { realfilepath = realfilepath.substring(1); } //만약 웹소스 내에 존재하지 않는 파일일 경우 //defaultfilepath + realfilepath 부분을 실제 경로로만 변경해주면 됨 File downloadfile = new File(defaultfilepath + realfilepath + realfilename); if (downloadfile.exists() && downloadfile.isFile()) { response.setContentType("application/octet-stream; charset=utf-8"); response.setContentLength((int) downloadfile.length()); OutputStream outputstream = null; FileInputStream inputstream = null; try { response.setHeader("Content-Disposition", getDisposition(realfilename, check_browser(request))); response.setHeader("Content-Transfer-Encoding", "binary"); outputstream = response.getOutputStream(); inputstream = new FileInputStream(downloadfile); //Spring framework 사용할 경우 //FileCopyUtils.copy(fis, out); //일반 자바/JSP 파일다운로드 byte[] buffer = new byte[1024]; int length = 0; while((length = inputstream.read(buffer)) > 0) { outputstream.write(buffer,0,length); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (inputstream != null){ inputstream.close(); } outputstream.flush(); outputstream.close(); } catch (Exception e2) {} } }else { System.out.println("파일존재하지 않음"); } } private String check_browser(HttpServletRequest request) { String browser = ""; String header = request.getHeader("User-Agent"); //신규추가된 indexof : Trident(IE11) 일반 MSIE로는 체크 안됨 if (header.indexOf("MSIE") > -1 || header.indexOf("Trident") > -1){ browser = "ie"; } //크롬일 경우 else if (header.indexOf("Chrome") > -1){ browser = "chrome"; } //오페라일경우 else if (header.indexOf("Opera") > -1){ browser = "opera"; } //사파리일 경우 else if (header.indexOf("Apple") > -1){ browser = "sarari"; } else { browser = "firfox"; } return browser; } private String getDisposition(String down_filename, String browser_check) throws UnsupportedEncodingException { String prefix = "attachment;filename="; String encodedfilename = null; System.out.println("browser_check:"+browser_check); if (browser_check.equals("ie")) { encodedfilename = URLEncoder.encode(down_filename, "UTF-8").replaceAll("\\+", "%20"); }else if (browser_check.equals("chrome")) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < down_filename.length(); i++){ char c = down_filename.charAt(i); if (c > '~') { sb.append(URLEncoder.encode("" + c, "UTF-8")); } else { sb.append(c); } } encodedfilename = sb.toString(); }else { encodedfilename = "\"" + new String(down_filename.getBytes("UTF-8"), "8859_1") + "\""; } return prefix + encodedfilename; } }
상단 사용은 객체 생성 후 "download" 메서드를 호출하는 것입니다.
우선 웹서버내에 파일이 등록되어있다 가정을 한후 jsp페이지를 호출해보도록 하겠습니다.
위에 이미지를 보시면 DownUtil.java 라는 클래스를 생성하여 상단 코드를 적용하였습니다.
이제 URL : download.jsp를 호출하여 roqkffhwk.xlsx 파일을 다운로드 받도록 해보겠습니다.
JSP 코드는 다음과 같습니다.
DownUtil downutil=new DownUtil(); downutil.download(request, response, "", "roqkffhwk.xlsx", "개발로짜.xlsx");
입력순서를 보시면
첫번째 parameter : request
두번째 parameter : response
세번째 parameter : 웹소스 상의 절대경로(""=웹루트 상단경로)
네번째 parameter : 다운로드받을 실제파일명
다섯번째 parameter : 다운로드후 사용자 pc에 다운로드 받기위한 원본파일명
(실제파일명을 넣어줘도 무관)
실행을 해보도록 해보겠습니다.
상단처럼 정상적으로 다운로드가 완료되었습니다.
하지만 콘솔 확인결과 Exception이 발생되었네요
getOutputStream() has already been called for this response Exception이 발생됐는대요
일반 SpringFrameWork의 경우 controller 같은곳에서 호출이 이루어 지므로 별도의 Exception이 발생되지 않습니다.
JSP페이지 내에서 해당 코드를 작성할 경우 response가 이미 호출되었는데 중복호출(?)로 인한 Exception이 발생하는걸로 알고있습니다.
이를 해결하기 위해서는
DownUtil downutil=new DownUtil();
위코드 바로 상단에
out.clear();
이라는 코드를 추가적으로 작성해주신다면 Exception이 발생되지 않고 정상적으로 파일다운로드가 이루어집니다.
그리고 다운로드 Util 샘플코드에 주석으로 spring용 wrtie코드인
FileCopyUtils.copy(fis, out);
부분을 해제해주시고 기존 byte white 부분을 주석처리 하신 후 사용하시면 되시겠습니다.
그럼 유용하시길...
by 개발로짜
JAVA opencsv를 이용하여 csv 파일생성하기 (2) | 2014.10.24 |
---|---|
자바 zxing를 이용하여 QR코드 생성 + 색상코드(hex,rgb,안드로이드그래픽색상) 적용법 (2) | 2014.10.16 |
자바 POI를 이용한 엑셀(xls,xlsx)에 들어있는 데이터들 읽어오기 (8) | 2014.10.07 |
POI라이브러리를 이용하여 엑셀파일(xls,xlsx) 에 데이터 넣어서 파일로 만들기 (1) | 2014.10.07 |
DTO,VO에 정의되어있는 변수명 및 갯수에 관계없이 변수명과 value값 한방에 가져오기 (0) | 2014.10.07 |
안녕하세요 개발로짜입니다.
지난 포스팅은 데이터들을 엑셀파일로 만드는 작업을 진행했었죠?
이번에는 이전 포스팅에 만든 엑셀파일을 반대로 읽어보는 내용을 진행하도록 하겠습니다.
지난 포스팅에서 만든 엑셀파일에 존재하는 데이터 출력입니다.
2014/10/07 - [코드저장소/java] - POI라이브러리를 이용하여 엑셀파일(xls,xlsx) 에 데이터 넣어서 파일로 만들기
위와 같이 엑셀파일내에 존재하는 내용들입니다.
이 생성된 파일을 콘솔에 각 셀마다 읽어보도록 하겠습니다.
이번에는 버전별 코드를 작성해보도록 하겠습니다.
//파일을 읽기위해 엑셀파일을 가져온다 FileInputStream fis=new FileInputStream("D:\\roqkffhwk.xls"); HSSFWorkbook workbook=new HSSFWorkbook(fis); int rowindex=0; int columnindex=0; //시트 수 (첫번째에만 존재하므로 0을 준다) //만약 각 시트를 읽기위해서는 FOR문을 한번더 돌려준다 HSSFSheet sheet=workbook.getSheetAt(0); //행의 수 int rows=sheet.getPhysicalNumberOfRows(); for(rowindex=1;rowindex<rows;rowindex++){ //행을 읽는다 HSSFRow row=sheet.getRow(rowindex); if(row !=null){ //셀의 수 int cells=row.getPhysicalNumberOfCells(); for(columnindex=0;columnindex<=cells;columnindex++){ //셀값을 읽는다 HSSFCell cell=row.getCell(columnindex); String value=""; //셀이 빈값일경우를 위한 널체크 if(cell==null){ continue; }else{ //타입별로 내용 읽기 switch (cell.getCellType()){ case HSSFCell.CELL_TYPE_FORMULA: value=cell.getCellFormula(); break; case HSSFCell.CELL_TYPE_NUMERIC: value=cell.getNumericCellValue()+""; break; case HSSFCell.CELL_TYPE_STRING: value=cell.getStringCellValue()+""; break; case HSSFCell.CELL_TYPE_BLANK: value=cell.getBooleanCellValue()+""; break; case HSSFCell.CELL_TYPE_ERROR: value=cell.getErrorCellValue()+""; break; } } System.out.println("각 셀 내용 :"+value); } } }
파일을 읽기위해 엑셀파일을 가져온다 FileInputStream fis=new FileInputStream("D:\\roqkffhwk2.xlsx"); XSSFWorkbook workbook=new XSSFWorkbook(fis); int rowindex=0; int columnindex=0; //시트 수 (첫번째에만 존재하므로 0을 준다) //만약 각 시트를 읽기위해서는 FOR문을 한번더 돌려준다 XSSFSheet sheet=workbook.getSheetAt(0); //행의 수 int rows=sheet.getPhysicalNumberOfRows(); for(rowindex=1;rowindex<rows;rowindex++){ //행을읽는다 XSSFRow row=sheet.getRow(rowindex); if(row !=null){ //셀의 수 int cells=row.getPhysicalNumberOfCells(); for(columnindex=0;columnindex<=cells;columnindex++){ //셀값을 읽는다 XSSFCell cell=row.getCell(columnindex); String value=""; //셀이 빈값일경우를 위한 널체크 if(cell==null){ continue; }else{ //타입별로 내용 읽기 switch (cell.getCellType()){ case XSSFCell.CELL_TYPE_FORMULA: value=cell.getCellFormula(); break; case XSSFCell.CELL_TYPE_NUMERIC: value=cell.getNumericCellValue()+""; break; case XSSFCell.CELL_TYPE_STRING: value=cell.getStringCellValue()+""; break; case XSSFCell.CELL_TYPE_BLANK: value=cell.getBooleanCellValue()+""; break; case XSSFCell.CELL_TYPE_ERROR: value=cell.getErrorCellValue()+""; break; } } System.out.println("각 셀 내용 :"+value); } } }
XLS 및 XLSX의 결과는 상단과 모두 동일하게 나올것입니다.
필요한 내용에따라 사용하도록 하세요 ㅎㅎ
by 개발로짜
자바 zxing를 이용하여 QR코드 생성 + 색상코드(hex,rgb,안드로이드그래픽색상) 적용법 (2) | 2014.10.16 |
---|---|
자바 다운로드 유틸을 만들어서 웹서버에 등록되있는 파일을 다운로드 하자 (5) | 2014.10.07 |
POI라이브러리를 이용하여 엑셀파일(xls,xlsx) 에 데이터 넣어서 파일로 만들기 (1) | 2014.10.07 |
DTO,VO에 정의되어있는 변수명 및 갯수에 관계없이 변수명과 value값 한방에 가져오기 (0) | 2014.10.07 |
Map객체의 key값을 읽어서 value값 한번에 추출하기 (0) | 2014.10.07 |
이번 포스팅은 엑셀규격에 데이터를 밀어넣는 작업을 진행해볼까 합니다.
엑셀 XLS,XLSX 버전 모두 포스팅 하도록 하겠습니다. ㅎㅎ
엑셀 2003 - 최대 입력할수 있는 데이터는 가로 256컬럼, 세로 65,536라인입니다.
엑셀 2007 - 최대 입력가능 데이터는 가로 16,384 세로 1,048,576 라인입니다.
엑셀을 쓰기위해 우선적으로 진행해야할 작업은 POI라는라이브러리를 다운로드 받는 일인대요
http://poi.apache.org/download.html
위 사이트 접속후 POI 라이브러리를 다운로드 받으시면 되겠습니다.
오늘날짜 기준으로 3.11은 BETA 버전이므로 3.10버전을 받도록 하겠습니다.
다운로드를 받으셨으면
압축해제후 다음 라이브러리를 이클립스의 lib 폴더에 넣고
작업을 진행해보도록 하겠습니다.
XLS 파일만 작성하실 분들은 상단 라이브러리만 IMPORT해주시면 되겠습니다.
추가로 2007버전인 XLSX파일을 생성하시고자 하실경우
"ooxml-lib" 디렉토리에 있는 라이브러리들을 추가적으로 IMPORT 해주셔야 합니다.
그럼 샘플 코드작성을 위해 임의의 시나리오를 작성해보겠습니다.
가상의 DB데이터를 담은 LIST객체의 데이터를 엑셀규격에 맞추어서 넣은다음 파일로 작성한다
그럼 위 시나리오에 맞추어 다음 코드를 보시겠습니다.
DB데이터를 담는 객체는 map 타입으로 진행을 하도록 하겠습니다.
같은 코드를 2003,2007 버전으로 나누어서 작성하도록 하겠습니다.
//임의의 VO가 되주는 MAP 객체 Map<String,Object>map=null; //가상 DB조회후 목록을 담을 LIST객체 ArrayList<Map<String,Object>> list=new ArrayList<Map<String,Object>>(); ArrayList<String> columnList=new ArrayList<String>(); //DB조회후 데이터를 담았다는 가상의 데이터 for(int i=0;i<10;i++){ map=new HashMap<String,Object>(); map.put("seq", i+1); map.put("title", "제목이다"+i); map.put("content", "내용입니다"+i); list.add(map); } //MAP의 KEY값을 담기위함 if(list !=null &&list.size() >0){ //LIST의 첫번째 데이터의 KEY값만 알면 되므로 Map<String,Object> m=list.get(0); //MAP의 KEY값을 columnList객체에 ADD for(String k : m.keySet()){ columnList.add(k); } } //1차로 workbook을 생성 HSSFWorkbook workbook=new HSSFWorkbook(); //2차는 sheet생성 HSSFSheet sheet=workbook.createSheet("시트명"); //엑셀의 행 HSSFRow row=null; //엑셀의 셀 HSSFCell cell=null; //임의의 DB데이터 조회 if(list !=null &&list.size() >0){ int i=0; for(Map<String,Object> mapobject : list){ // 시트에 하나의 행을 생성한다(i 값이 0이면 첫번째 줄에 해당) row=sheet.createRow((short)i); i++; if(columnList !=null &&columnList.size() >0){ for(int j=0;j<columnList.size();j++){ //생성된 row에 컬럼을 생성한다 cell=row.createCell(j); //map에 담긴 데이터를 가져와 cell에 add한다 cell.setCellValue(String.valueOf(mapobject.get(columnList.get(j)))); } } } } FileOutputStream fileoutputstream=new FileOutputStream("D:\\roqkffhwk.xls"); //파일을 쓴다 workbook.write(fileoutputstream); //필수로 닫아주어야함 fileoutputstream.close(); System.out.println("엑셀파일생성성공");
//임의의 VO가 되주는 MAP 객체 Map<String,Object>map=null; //가상 DB조회후 목록을 담을 LIST객체 ArrayList<Map<String,Object>> list=new ArrayList<Map<String,Object>>(); ArrayList<String> columnList=new ArrayList<String>(); //DB조회후 데이터를 담았다는 가상의 데이터 for(int i=0;i<10;i++){ map=new HashMap<String,Object>(); map.put("seq", i+1); map.put("title", "제목이다"+i); map.put("content", "내용입니다"+i); list.add(map); } //MAP의 KEY값을 담기위함 if(list !=null &&list.size() >0){ //LIST의 첫번째 데이터의 KEY값만 알면 되므로 Map<String,Object>m=list.get(0); //MAP의 KEY값을 columnList객체에 ADD for(String k : m.keySet()){ columnList.add(k); } } //1차로 workbook을 생성 XSSFWorkbook workbook=new XSSFWorkbook(); //2차는 sheet생성 XSSFSheet sheet=workbook.createSheet("시트명"); //엑셀의 행 XSSFRow row=null; //엑셀의 셀 XSSFCell cell=null; //임의의 DB데이터 조회 if(list !=null &&list.size() >0){ int i=0; for(Map<String,Object>mapobject : list){ // 시트에 하나의 행을 생성한다(i 값이 0이면 첫번째 줄에 해당) row=sheet.createRow((short)i); i++; if(columnList !=null &&columnList.size() >0){ for(int j=0;j<columnList.size();j++){ //생성된 row에 컬럼을 생성한다 cell=row.createCell(j); //map에 담긴 데이터를 가져와 cell에 add한다 cell.setCellValue(String.valueOf(mapobject.get(columnList.get(j)))); } } } } FileOutputStream fileoutputstream=new FileOutputStream("D:\\roqkffhwk2.xlsx"); //파일을 쓴다 workbook.write(fileoutputstream); //필수로 닫아주어야함 fileoutputstream.close(); System.out.println("엑셀파일생성성공");
xlsx 코드는 거의 동일하고 사용 API만 변경되었을 뿐입니다.
기존 "HSSFXXX" 시작된 API들을 "XSSFXXX" 로 변경되고
추가로 파일명의 확장자를 "파일명.xlsx"으로 변경만 해주시면 됩니다.
Map타입으로 데이터를 담아서 엑셀에 쓰기작업을 진행하였으나
dto,vo 객체를 이용하여 쓰는것 또한 가능합니다.
2014/10/07 - [코드저장소/java] - Map객체의 key값을 읽어서 value값 한번에 추출하기
2014/10/07 - [코드저장소/java] - DTO,VO에 정의되어있는 변수명 및 갯수에 관계없이 변수명과 value값 한방에 가져오기
각 링크를 참고하여 같이 적용하시면 되실거 같네요
한번 실행을 해보도록 하겠습니다.(2003,2007 동일결과)
위와같이 console에 "엑셀파일생성"이라는 문구가 출력되었습니다.
그렇다면 정상적으로 생성이 되었나 파일을 확인하도록 하겠습니다.
정상적으로 종류별로 모든 데이터가 엑셀에 생성이 되었습니다 ^^
엑셀파일 읽기관련 포스팅은 하단 글을 참조하세요
↓↓↓↓↓↓↓
2014/10/07 - [코드저장소/java] - 자바 POI를 이용한 엑셀(xls,xlsx)에 들어있는 데이터들 읽어오기
by 개발로짜
자바 다운로드 유틸을 만들어서 웹서버에 등록되있는 파일을 다운로드 하자 (5) | 2014.10.07 |
---|---|
자바 POI를 이용한 엑셀(xls,xlsx)에 들어있는 데이터들 읽어오기 (8) | 2014.10.07 |
DTO,VO에 정의되어있는 변수명 및 갯수에 관계없이 변수명과 value값 한방에 가져오기 (0) | 2014.10.07 |
Map객체의 key값을 읽어서 value값 한번에 추출하기 (0) | 2014.10.07 |
JSTL의 c:forTokens을 이용하여 확장자명 찾기 (0) | 2014.10.06 |