일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 게시판
- object
- 출처 : https://joshua1988.github.io/web-development/javascript/promise-for-beginners/
- toString
- https://velog.io/@velopert/create-typescript-react-component
- 출처 : https://webdir.tistory.com/506
- http://jeonghwan-kim.github.io/dev/2019/06/25/react-ts.html
- Today
- Total
Back Ground
파일 다운로드 처리 (File Download) 본문
스프링에서 지원해주는 File Download
기본적인 흐름은 이렇다
1. 파일링크를 클릭할때 컨트롤러 클래스에게 파일 패스와 파일이름을 던져주고 [Controller에서 file_path를 지정해도 된다.] |
2. 받은 컨트롤러 클래스에서 그 파일패스와 파일이름으로 file을 만들어 (Download Controller) |
3. 뷰로 전달을 할 것이다. |
4. 그럼 뷰에서 받은 file정보를 이용해서 실제 파일을 읽어드린 다음 원하는 위치에 쓰는 작업을 한다. (DownloadView) |
일반적인 컨트롤러 클래스에서 작업한 후, 뷰 페이지로 결과값을 뿌려주는 것인데
일반적으로 뷰 페이지 JSP페이지였다.
하지만 다운로드에 사용 될 뷰는 JSP가 아니라 클래스 파일 이다.
그렇기 때문에 아래처럼 일반적으로 사용하던 viewResolver가 처리하는 것이 아니라
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="order"> <value>1</value> </property>
</bean> |
tip: <property name="order" value="1"/> 으로 간략하게 적어도 상관없다.
downlonad만을 처리하는 viewResolver가 따로 존재해야 한다. 여기에는 id값이 없다 (-주의할것-)
[하지만 id를 downloadViewResolver 라고 지정 해 놓은 것 처럼 사용 해도 되는듯 하다 ]
참고 : http://snoopy81.tistory.com/325
<bean id="downloadViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order"> <value>0</value> </property> </bean> |
tip: <property name="order" value="0"/> 으로 간략하게 적어도 상관없다.
주의할 점은 위 두 코드에 포함된 프로퍼티를 보면 "order" 라는 프로퍼티가 있는데
이 프로퍼티는 두개 이상 존재하는 viewResolver를 위해서 우선순위를 매기는 것이다.
우선순위는 "0"이 가장 먼저 실행되고, 이후 매겨지는 순서에 따라 실행된다 0~...
다음 viewResolver가 실행되는 기준은 "null"이 반환되느냐 가 기준이다.
(즉, 우선순위 0이 null이 반환될때 1이 실행된다)
그렇기 때문에 Null값이 있을 수 없는 InternalResourceViewResolver 가 우선순위가 높게 되면,
다른 viewResolver는 사용되지 않게 되는 문제가 있다.
(그렇기 때문에 BeanNameViewResolver에 order의 우선순의를 "0"으로 한것.)
그래서 InternalResourceViewResolver은 우선순위가 가장 낮아야 한다.
이제 BeanNameViewResolver의 사용하는 방법을 알아본다.
BeanNameViewResolver(파일 다운로드 viewResolver) "null"이 반환되지 않는다면 (즉, 컨트롤러 클래스에서 리턴 되 온 뷰페이지 값과 일치하는 빈이 있는 경우) 컨트롤러 클래스에서 리턴 되 온 뷰페이지 값과 일치하는 빈이 등록되있는 경우는 빈에 해당하는 컨트롤러 클래스가 파일 다운로드를 처리하게 된다.
그렇기 때문에 컨트롤러 클래스에서 viewResolver로 던져 줄 뷰 페이지 이름과 처리할 view 클래스 빈 이름이 같아야 한다. (이 말을 반대로 하자면, 실제 jsp가 보여져야 될 때는 리턴값과 view 빈 이름이 같아서는 절대 안된다.) <bean id="download" class="Spring.DownloadView"/> - 이 코드가 다운로드를 처리할 뷰 클래스를 등록하는 것이다. 저기 id="download"라고 되있는 부분과, 클래스에서 리턴된 값이 같아야 한다. 그리고 url을 처리할 컨트롤러 클래스도 등록되야한다. <bean id="down" class="Spring.DownloadController"/> |
여기 까지가 좀 복잡하지만 servlet.xml 파일을 설정하는 부분이다.
하나하나 천천히 다시 읽어보면 이해가 될 것이다.
이제 처음부터 하나씩 따라가보자.
파일 이름에 링크를 걸어서 컨트롤러 클래스로 넘기는 부분부터 시작
.jsp
<a href="/Spring/download.do?path=${path}&fileName=${itemBean.fileName}"> ${itemBean.fileName}</a> |
download.do로 파일네임과 패스를 넘긴다.
패스를 넘겨 받지 않는 다면?
(현재 진행 중이였던 프로젝트에선 catalina.properties에 파일패스를 넣고 불러오는 식으로 사용했다.
나중에 패치를 해줄때 경로를 변경되지 않고 server에 프로그램 배포 시 고정으로 해두기 위함이다. )
- 현 프로젝트에서는 ....
catalina.properties
SERVER_FILE_PATH=C:/file_download/ |
DownloadController.java
public ModelAndView download(HttpServletRequest request) throws Exception { String filePath = System.getProperty("SERVER_FILE_PATH"); //catalina.properties if(filePath == null || filePath.equals("")== true){ filePath = message.getMessage("SERVER_FILE_PATH"); //message if(filePath == null || filePath.equals("")== true){ throw new Exception("현재 프로그램 파일 다운로드 경로가 존재하지 않습니다."); } } |
만일을 위해 message.properties에도 저장해 뒀다.
그럼 본론으로 돌아가 jsp의 url을 처리하는 컨트롤 클래스는
<bean id="down" class="Spring.DownloadController"/>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @Controller public class DownloadController implements ApplicationContextAware{ private WebApplicationContext context = null; @RequestMapping("download.do") public ModelAndView download(@RequestParam("path")String path, @RequestParam("fileName")String fileName){ String fullPath = path + "\\" + fileName; File file = new File(fullPath); return new ModelAndView("download", "downloadFile", file); } @Override public void setApplicationContext(ApplicationContext arg0) throws BeansException { // TODO Auto-generated method stub this.context = (WebApplicationContext)arg0; } } | cs |
@RequestMapping("download.do") 어노테이션으로 지정해준 것 처럼
download.do가 들어오면 메소드가 동작한다.
링크에서 준것처럼 패스와 파일네임을 받아서
파일에 조합해서 쓰고 "download" 뷰 페이지로 파일을 "downloadFile"이름으로 삽입하고 리턴 시킨다.
그러면 <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
저 viewResolver가 먼저 리턴을 처리하려 할 것이다.
"download"로 등록된 빈이 있는지 찾아 보는데 우리는 아까 "download"로 뷰 클래스를 등록시켜 놓았다.
<bean id="download" calss="Spring.DownloadView"/>
이제 DownlaodView.java 클래스가 뷰 페이지로 동작할 것이다.
뷰 페이지에서는 map에 등록된 파일을 이용해서 encoding 설정과 헤더 설정을 해준 후 파일을 지정위치에 쓴다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | import java.io.File; import java.io.FileInputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.util.FileCopyUtils; import org.springframework.web.servlet.view.AbstractView; public class DownloadView extends AbstractView { public void Download(){ setContentType("application/download; utf-8"); } @Override protected void renderMergedOutputModel(Map<string, object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // TODO Auto-generated method stub File file = (File)model.get("downloadFile"); System.out.println("DownloadView --> file.getPath() : " + file.getPath()); System.out.println("DownloadView --> file.getName() : " + file.getName()); response.setContentType(getContentType()); response.setContentLength((int)file.length()); String userAgent = request.getHeader("User-Agent"); boolean ie = userAgent.indexOf("MSIE") > -1; String fileName = null; if(ie){ fileName = URLEncoder.encode(file.getName(), "utf-8"); } else { fileName = new String(file.getName().getBytes("utf-8")); }// end if; response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";"); response.setHeader("Content-Transfer-Encoding", "binary"); OutputStream out = response.getOutputStream(); FileInputStream fis = null; try { fis = new FileInputStream(file); FileCopyUtils.copy(fis, out); } catch(Exception e){ e.printStackTrace(); }finally{ if(fis != null){ try{ fis.close(); }catch(Exception e){} } }// try end; out.flush(); }// render() end; } | cs |
여기까지가
파일링크를 클랙해서 다운로드를 하는 일련의 과정을 코드로 풀어 놓은 것이다.
참고 :http://winmargo.tistory.com/103
여기서 더 추가를 하자면
Metis_NoticeBoardServiceController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public ModelAndView insertBoard(HttpServletRequest request, @ModelAttribute Metis_NoticeBoardServiceParam noticeboardserviceparam ) throws Exception{ JSONObject returnObject= new JSONObject(); try{ MultipartFile file_data1 = noticeboardserviceparam.getFile_data1(); MultipartFile file_data2 = noticeboardserviceparam.getFile_data2(); MultipartFile file_data3 = noticeboardserviceparam.getFile_data3(); MultipartFile file_data4 = noticeboardserviceparam.getFile_data4(); MultipartFile file_data5 = noticeboardserviceparam.getFile_data5(); Map<String,MultipartFile> map = new HashMap<String,MultipartFile>(); if(file_data1 != null && file_data1.getSize() > 0) map.put("file_data1", file_data1); if(file_data2 != null && file_data2.getSize() > 0) map.put("file_data2", file_data2); if(file_data3 != null && file_data3.getSize() > 0) map.put("file_data3", file_data3); if(file_data4 != null && file_data4.getSize() > 0) map.put("file_data4", file_data4); if(file_data5 != null && file_data5.getSize() > 0) map.put("file_data5", file_data5); JSONObject param = parameterTransJSONObject.getJSONObject(noticeboardserviceparam); param.put("operator_ip", request.getRemoteAddr()); returnObject = metis_noticeboardscreenflow.insertBoard(param,map); }catch(Exception e) { if(returnObject.has("status") == false){ returnObject.put("status","ERROR"); } if(returnObject.has("statusDescription") == false){ returnObject.put("statusDescription","오류가 발생 했습니다."); } log4jLogManager.debug(logger, e); } request.setAttribute("result", returnObject); return new ModelAndView("/result.jsp"); } | cs |
다수로 file을 받기 위해 MultipartFile를
Map형태로 담아 서비스까지 파일을 보내줬다.
(파일은 트랜젝션 처리가 되지않기 때문에 가장 마지막에 처리하기 위함)
원본 파일명을 저장하면 파일이름의 중복되어 물리적으로 저장시 문제가 발생한다.
그렇기 때문에 파일이름을 난수로 바꾼후
- 원본 파일명 |
- 확장자 |
- 랜덤 파일명 |
을 만들어 준다.
originalFileName = file_data.getOriginalFilename(); originalFileExtension = originalFileName.substring(originalFileName.lastIndexOf(".")); //.까지 잘라낸다 (확장자를 알기 위해서) storedFileName = getRandomString() + originalFileExtension;//랜덤문자열 + 확장자
|
NoticeBoardServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | @Override @Transactional(propagation=Propagation.REQUIRED, rollbackFor={Exception.class}) public JSONObject insertBoard(JSONObject param,Map<String, MultipartFile> MultipartMap) throws Exception { File file= null; if(MultipartMap != null){ /**저장 경로 */ String file_url = System.getProperty("SERVER_FILE_PATH"); if(file_url == null || file_url.equals("")==true){ file_url = message.getMessage("SERVER_FILE_PATH"); } //String file_url = catalina_base; //+System.getProperty("file.separator")+"download"+System.getProperty("file.separator")+"BTLMS"+System.getProperty("file.separator")+"NOTICE"+System.getProperty("file.separator"); file = new File(file_url); if(file.exists() == false){//파일과 디렉토리가 실제로 존재하지 않다면 file.mkdirs(); //디렉토리를 만든다. } Map<String,Object> fMap = new HashMap<String, Object>(); MultipartFile file_data =null; String originalFileName =""; String originalFileExtension=""; String storedFileName =""; Long size =null; byte[] bytes =null; for(int i=1;6>i;i++){ file_data = MultipartMap.get("file_data"+i); if(file_data != null){ originalFileName = file_data.getOriginalFilename(); originalFileExtension = originalFileName.substring(originalFileName.lastIndexOf(".")); //.까지 잘라낸다 (확장자를 알기 위해서) storedFileName = getRandomString() + originalFileExtension;//랜덤문자열 + 확장자 size = file_data.getSize(); bytes = file_data.getBytes(); fMap.put("FILE_KEY" ,noticeboardDAO.getSEQKey()); fMap.put("METIS_NOTICE_KEY" ,metis_notice_key); fMap.put("ORIGINAL_FILE_NAME",originalFileName); fMap.put("STORED_FILE_NAME" ,storedFileName); fMap.put("FILE_EXTENSION" ,originalFileExtension); fMap.put("FILE_BYTES" ,bytes.toString()); fMap.put("FILE_SIZE" ,size); fMap.put("FILE_ADDRESS" ,file_url); fMap.put("FIRST_WORK" ,first_work); noticeboardDAO.insert_file(fMap); /**파일 첨부*/ file = new File(file_url + storedFileName); file_data.transferTo(file); //파일복사 임시 메모리 저장 file.createNewFile(); } } } return resultObject; } | cs |
이런식으로 DB에 저장해 준다.
이제는 다운로드 받을때다.
다운로드 하려는 파일의
물리적 주소에 저장되 있는 랜덤 파일명 과
기존의 입력 할 때의 원본파일명 을
화면에서 넘겨 받는다.
(굳이 DB에서 끄내지 않고 사용하기 위해서 프런트에서 보내준다.)
DownloadController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @RequestMapping("/fileDownload.do") public ModelAndView download(HttpServletRequest request) throws Exception { String filePath = System.getProperty("SERVER_FILE_PATH"); //catalina.properties if(filePath == null || filePath.equals("")== true){ filePath = message.getMessage("SERVER_FILE_PATH"); //message if(filePath == null || filePath.equals("")== true){ throw new Exception("현재 프로그램 파일 다운로드 경로가 존재하지 않습니다."); } } File downloadFile = null; if(request.getParameter("original_file_name") != null){ /******************************************** * 원본 이름으로 변경 후 내보낼때 사용 (공지사항 다운로드) ********************************************/ File file_original = new File(filePath+request.getParameter("original_file_name"));//원본 파일 명 File file_stored = new File(filePath+request.getParameter("stored_file_name")); //변경된 파일 명 try{ if( file_stored.exists() == true) file_stored.renameTo( file_original );//이름변경 }catch(Exception e){ throw new Exception("존재 하지 않는 변경 파일명 입니다."); } downloadFile = new File(filePath + request.getParameter("original_file_name")); }else{ downloadFile = new File(filePath + request.getParameter("fileName")); } return new ModelAndView("downloadView", "downloadFile", downloadFile); //바이트로 보내준다 } | cs |
File file_original = new File(filePath+request.getParameter("original_file_name"));//원본 파일 명 File file_stored = new File(filePath+request.getParameter("stored_file_name")); //변경된 파일 명
|
jsp에서 원본 파일명과 변경된 파일명을 받아
if( file_stored.exists() == true) file_stored.renameTo( file_original );//이름변경
|
파일이 저장된 물리적 주소에 랜덤 파일명을 원본 파일명으로 변경 해준다.
그런 후 DownloadView.java로 반환시켜 준다.
return new ModelAndView("downloadView", "downloadFile", downloadFile); //바이트로 보내준다
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | public class DownloadView extends AbstractView { /** * */ public DownloadView() { setContentType("application/download; charset=utf-8"); } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { File file = (File)model.get("downloadFile"); response.setContentType(getContentType()); response.setContentLength((int)file.length()); String userAgent = request.getHeader("User-Agent"); boolean ie = userAgent.indexOf("MSIE") > -1; String fileName = null; if(ie) { fileName = URLEncoder.encode(file.getName(), "utf-8"); } else { fileName = new String(file.getName().getBytes("utf-8"), "iso-8859-1"); } response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";"); response.setHeader("Content-Transfer-Encoding", "binary"); OutputStream out = response.getOutputStream(); FileInputStream fis = null; try { fis = new FileInputStream(file); FileCopyUtils.copy(fis, out); } finally { if(fis != null) { try { fis.close(); } catch(IOException ioe) {} } } out.flush(); /**다운로드 후 다시 변경된 이름으로 변경 */ if(request.getParameter("stored_file_name") != null){ File original_file= new File(file.getPath()); //원본 경로+파일 String file_path = original_file.toString().replace(file.getName(),""); //path 추출 File stored_file = new File(file_path+request.getParameter("stored_file_name"));//변경 파일명 original_file.renameTo(stored_file);//이름 변경 } } } | cs |
DownloadView 처리가 다 된 후
다시 한번 원본 파일명을 랜덤 파일명으로 변경해준다.
if(request.getParameter("stored_file_name") != null){ File original_file= new File(file.getPath()); //원본 경로+파일 String file_path = original_file.toString().replace(file.getName(),""); //path 추출 File stored_file = new File(file_path+request.getParameter("stored_file_name"));//변경 파일명 original_file.renameTo(stored_file);//이름 변경 }
|
이유는 다운로드시 랜덤파일명으로 사용자가 받게 되는 걸 방지하고
다운로드 됐을때 원본 파일명으로 변경이 되어 있기때문에 중복되고 파일명이 일치하지 않아서 다음번에 다운로드 시 문제가 생긴다.
이런 방법으로 하면 여러 파일을 저장하고 다운로드 받을 수 있다.
File Download supported by Spring
The basic flow is like this
1. When clicking the file link, throw the file path and file name to the controller class. [You can specify file_path in Controller.] |
2. Create a file with the file path and file name in the received controller class (Download Controller) |
3. We are going to pass the view. |
4. Then, read the actual file using the file information received from the view and write it to the desired location. (DownloadView) |
After working in the general controller class, the result is displayed in the view page.
In general, it was a view page JSP page .
However, the view to be used for download is not a JSP but a class file .
That's why viewResolver, which is commonly used as below, does not handle it.
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="order"> <value>1</value> </property>
</bean> |
tip: <property name="order" value="1"/ > Briefly, it doesn't matter.
There should be a separate viewResolver that handles downlonad only. There is no id value here (-notice-)
[But you can use it as if you specified id as downloadViewResolver]
Reference: http://snoopy81.tistory.com/325
<bean id="downloadViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order"> <value>0</value> </property> </bean> |
tip: <property name="order" value="0"/ > Briefly, it doesn't matter.
If you look at the properties included in the above two codes, there is a property called "order".
This property is prioritized for more than one viewResolver .
The priority is " 0" is executed first , followed by the order in which it is assigned 0~...
The next viewResolver is executed based on whether "null " is returned.
(I.e. 1 is executed when priority 0 is returned null)
That's why when the InternalResourceViewResolver that cannot have null values has a higher priority ,
Another viewResolver is not used.
(That's why the order of priority in the BeanNameViewResolver is "0 ". )
So, InternalResourceViewResolver should have the lowest priority.
Now let's see how to use BeanNameViewResolver .
BeanNameViewResolver (file download viewResolver) If "null" is not returned (i.e., there is a bean that matches the viewpage value returned from the controller class) If a bean matching the view page value returned from the controller class is registered , The controller class corresponding to the bean handles file download .
That's why I'll throw it from controller class to viewResolver The view page name and the view class bean name to be processed must be the same. (To reverse this, when the actual jsp should be viewed, the return value and the view bean name must never be the same.) <bean id="download" class="Spring.DownloadView"/> -This code registers the view class to handle the download. There should be the same id="download" and the value returned from the class. Also, a controller class to handle url must be registered. <bean id="down" class="Spring.DownloadController"/> |
This is a bit complicated, but it is the part that configures the servlet.xml file.
Read it one by one slowly and it will make sense.
Now let's go one by one from the beginning.
Start by linking to the file name and passing it to the controller class.
.jsp
<a href="/Spring/download.do?path=${path}&fileName=${itemBean.fileName}"> ${itemBean.fileName}</a> |
Pass the file name and path to download.do.
What if you don't pass the pass?
(In the current project, I used it by loading the file path in catalina.properties.
This is to fix the path when the program is distributed to the server without changing the path when patching later. )
-In the current project...
catalina.properties
SERVER_FILE_PATH=C:/file_download/ |
DownloadController.java
public ModelAndView download(HttpServletRequest request) throws Exception { String filePath = System.getProperty("SERVER_FILE_PATH"); //catalina.properties if(filePath == null || filePath.equals("")== true){ filePath = message.getMessage("SERVER_FILE_PATH"); //message if(filePath == null || filePath.equals("")== true){ throw new Exception("The current program file download path does not exist."); } } |
I saved it in message.properties just in case.
Then back to the main subject, the control class that handles the url of jsp
<bean id="down" class="Spring.DownloadController"/>
One 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @Controller public class DownloadController implements ApplicationContextAware{ private WebApplicationContext context = null; @RequestMapping("download.do") public ModelAndView download(@RequestParam("path")String path, @RequestParam("fileName")String fileName){ String fullPath = path + "\\" + fileName; File file = new File(fullPath); return new ModelAndView("download", "downloadFile", file); } @Override public void setApplicationContext(ApplicationContext arg0) throws BeansException { // TODO Auto-generated method stub this.context = (WebApplicationContext)arg0; } } | cs |
As if you specified it with the @RequestMapping("download.do") annotation
When download.do comes in, the method works.
Take the path and file name as given in the link
Write in combination with the file, insert the file into the "download" view page with the name "downloadFile" and return.
그러면 <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
That viewResolver will try to handle the return first.
We look for any bins registered as "download". We previously registered the view class as "download".
<bean id="download" calss="Spring.DownloadView"/>
Now the DownlaodView.java class will act as the view page.
On the view page, set encoding and header settings using the file registered in the map, and then write the file in the designated location.
One 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | import java.io.File; import java.io.FileInputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.util.FileCopyUtils; import org.springframework.web.servlet.view.AbstractView; public class DownloadView extends AbstractView { public void Download(){ setContentType("application/download; utf-8"); } @Override protected void renderMergedOutputModel(Map<string, object=""> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // TODO Auto-generated method stub File file = (File)model.get("downloadFile"); System.out.println("DownloadView --> file.getPath() : " + file.getPath()); System.out.println("DownloadView --> file.getName() : " + file.getName()); response.setContentType(getContentType()); response.setContentLength((int)file.length()); String userAgent = request.getHeader("User-Agent"); boolean ie = userAgent.indexOf("MSIE") > -1; String fileName = null; if(ie){ fileName = URLEncoder.encode(file.getName(), "utf-8"); } else { fileName = new String(file.getName().getBytes("utf-8")); }// end if; response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";"); response.setHeader("Content-Transfer-Encoding", "binary"); OutputStream out = response.getOutputStream(); FileInputStream fis = null ; try { fis = new FileInputStream(file); FileCopyUtils.copy(fis, out); } catch(Exception e){ e.printStackTrace (); }finally{ if (fis ! = null ) { try{ fis.close (); }catch(Exception e){} } }// try end; out.flush(); } // render () end; } | cs |
So far
The sequence of downloading a file by clicking the file link is unpacked with code.
Note: http://winmargo.tistory.com/103
The more additional gritty of
Metis_NoticeBoardServiceController.java
One 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public ModelAndView insertBoard(HttpServletRequest request, @ModelAttribute Metis_NoticeBoardServiceParam noticeboardserviceparam ) throws Exception{ JSONObject returnObject= new JSONObject(); try{ MultipartFile file_data1 = noticeboardserviceparam.getFile_data1(); MultipartFile file_data2 = noticeboardserviceparam.getFile_data2(); MultipartFile file_data3 = noticeboardserviceparam.getFile_data3(); MultipartFile file_data4 = noticeboardserviceparam.getFile_data4(); MultipartFile file_data5 = noticeboardserviceparam.getFile_data5(); Map<String,MultipartFile> map = new HashMap<String,MultipartFile>(); if(file_data1 != null && file_data1.getSize() > 0) map.put("file_data1", file_data1); if(file_data2 != null && file_data2.getSize() > 0) map.put("file_data2", file_data2); if(file_data3 != null && file_data3.getSize() > 0) map.put("file_data3", file_data3); if(file_data4 != null && file_data4.getSize() > 0) map.put("file_data4", file_data4); if(file_data5 != null && file_data5.getSize() > 0) map.put("file_data5", file_data5); JSONObject param = parameterTransJSONObject.getJSONObject(noticeboardserviceparam); param.put("operator_ip", request.getRemoteAddr()); returnObject = metis_noticeboardscreenflow.insertBoard(param,map); }catch(Exception e) { if(returnObject.has("status") == false){ returnObject.put("status","ERROR"); } if(returnObject.has("statusDescription") == false){ returnObject.put( "statusDescription" , "An error has occurred." ); } log4jLogManager.debug (logger, e); } request.setAttribute("result", returnObject); return new ModelAndView("/result.jsp"); } | cs |
MultipartFile to receive multiple files
The file was sent in the form of a map to the service.
(The file is not processed at the end of the transaction, so it is processed last)
If the original file name is saved, the file name is duplicated and a problem occurs when physically saving.
So after changing the file name to a random number
-Original file name |
- extension |
-Random file name |
Makes it.
originalFileName = file_data.getOriginalFilename(); originalFileExtension = originalFileName.substring(originalFileName.lastIndexOf(".")); Cut it down to //. (to know the extension) storedFileName = getRandomString() + originalFileExtension;//random string + extension
|
NoticeBoardServiceImpl.java
One 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | @Override @Transactional(propagation=Propagation.REQUIRED, rollbackFor={Exception.class}) public JSONObject insertBoard(JSONObject param,Map<String, MultipartFile> MultipartMap) throws Exception { File file= null; if(MultipartMap != null){ /**Storage path */ String file_url = System.getProperty("SERVER_FILE_PATH"); if(file_url == null || file_url.equals("")==true){ file_url = message.getMessage("SERVER_FILE_PATH"); } //String file_url = catalina_base; //+System.getProperty("file.separator")+"download"+System.getProperty("file.separator")+"BTLMS"+System.getProperty("file.separator")+"NOTICE"+System.getProperty("file.separator"); file = new File(file_url); if (file.exists() = = false ){ //If the files and directories don't actually exist file.mkdirs(); //Create a directory. } Map<String,Object> fMap = new HashMap<String, Object>(); MultipartFile file_data =null; String originalFileName =""; String originalFileExtension=""; String storedFileName =""; Long size =null; byte[] bytes =null; for(int i=1;6>i;i++){ file_data = MultipartMap.get("file_data"+i); if(file_data != null){ originalFileName = file_data.getOriginalFilename(); originalFileExtension = originalFileName. the substring (OriginalFileName. lastIndexOf ( "." )); Cut it down to //. (to know the extension) storedFileName = getRandomString() + originalFileExtension; //Random string + extension size = file_data.getSize(); bytes = file_data.getBytes(); fMap.put("FILE_KEY" ,noticeboardDAO.getSEQKey()); fMap.put("METIS_NOTICE_KEY" ,metis_notice_key); fMap.put("ORIGINAL_FILE_NAME",originalFileName); fMap.put("STORED_FILE_NAME" ,storedFileName); fMap.put("FILE_EXTENSION" ,originalFileExtension); fMap.put("FILE_BYTES" ,bytes.toString()); fMap.put("FILE_SIZE" ,size); fMap.put("FILE_ADDRESS" ,file_url); fMap.put("FIRST_WORK" ,first_work); noticeboardDAO.insert_file(fMap); /**Attachments*/ file = new File(file_url + storedFileName); file_data.transferTo(file); //Save temporary memory for copying files file.createNewFile(); } } } return resultObject; } | cs |
It is stored in the DB in this way.
Now, when you download it.
Of the file you want to download
Random file name and physical address
When the input of the existing source file name to
Take it from the screen.
(It is sent from the front desk for use without taking it out of the DB.)
DownloadController.java
One 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @RequestMapping("/fileDownload.do") public ModelAndView download(HttpServletRequest request) throws Exception { String filePath = System.getProperty("SERVER_FILE_PATH"); //catalina.properties if(filePath == null || filePath.equals("")== true){ filePath = message.getMessage("SERVER_FILE_PATH"); //message if(filePath == null || filePath.equals("")== true){ throw new Exception( "The current program file download path does not exist." ); } } File downloadFile = null; if(request.getParameter("original_file_name") != null){ /******************************************** * Used to export after changing to the original name (download notice) ********************************************/ File file_original = new File(filePath+request.getParameter("original_file_name"));//원본 파일 명 File file_stored = new File(filePath+request.getParameter("stored_file_name")); //변경된 파일 명 try{ if( file_stored.exists() == true) file_stored.renameTo( file_original );//이름변경 }catch(Exception e){ throw new Exception( "The name of the change file does not exist." ); } downloadFile = new File(filePath + request.getParameter("original_file_name")); }else{ downloadFile = new File(filePath + request.getParameter("fileName")); } return new ModelAndView("downloadView", "downloadFile", downloadFile); //바이트로 보내준다 } | cs |
File file_original = new File(filePath+request.getParameter("original_file_name"));//원본 파일 명 File file_stored = new File(filePath+request.getParameter("stored_file_name")); //변경된 파일 명
|
Get the original file name and changed file name from jsp
if( file_stored.exists() == true) file_stored.renameTo( file_original );//이름변경
|
Change the random file name to the original file name at the physical address where the file is stored.
Then, it returns to DownloadView.java .
return new ModelAndView("downloadView", "downloadFile", downloadFile); //바이트로 보내준다
|
One 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | public class DownloadView extends AbstractView { /** * */ public DownloadView() { setContentType("application/download; charset=utf-8"); } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { File file = (File)model.get("downloadFile"); response.setContentType(getContentType()); response.setContentLength((int)file.length()); String userAgent = request.getHeader("User-Agent"); boolean ie = userAgent.indexOf("MSIE") > -1; String fileName = null; if(ie) { fileName = URLEncoder.encode(file.getName(), "utf-8"); } else { fileName = new String(file.getName().getBytes("utf-8"), "iso-8859-1"); } response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";"); response.setHeader("Content-Transfer-Encoding", "binary"); OutputStream out = response.getOutputStream(); FileInputStream fis = null ; try { fis = new FileInputStream(file); FileCopyUtils.copy(fis, out); } finally { if (fis ! = null ) { try { fis.close (); } catch (IOException ioe) {} } } out.flush(); /**After downloading, change the name again */ if(request.getParameter("stored_file_name") != null){ File original_file = new File(file.getPath()); // Original path + file String file_path = original_file.toString().replace(file.getName(),""); //path 추출 File stored_file = new File(file_path+request.getParameter("stored_file_name"));//변경 파일명 original_file.renameTo(stored_file); //Name change } } } | cs |
After DownloadView processing is finished
Once again, the original file name is changed to a random file name.
if(request.getParameter("stored_file_name") != null){ File original_file = new File(file.getPath()); // Original path + file String file_path = original_file.toString().replace(file.getName(),""); //path 추출 File stored_file = new File(file_path+request.getParameter("stored_file_name"));//변경 파일명 original_file.renameTo(stored_file); //Name change }
|
The reason is that it prevents the user from receiving a random file name when downloading
Since it is changed to the original file name when it is downloaded, it is duplicated and the file name does not match.
This way, you can save and download multiple files.
スプリングでサポートしてくれるFile Download
基本的な流れはこうだ
1.ファイルのリンクをクリックしたときに、コントローラクラスにファイルパスとファイル名を投げかけて [Controllerで file_path を指定しても良い。] |
2.受信したコントローラクラスで、そのファイルのパスとファイル名にfileを作成(Download Controller) |
3.ビュー伝達を行うものである。 |
4.次に、ビューから受信したfileの情報を利用して、実際のファイルを読み込んだ次の目的の場所への書き込みをする。 (DownloadView) |
一般的なコントローラクラスで作業した後、ビューのページに結果の値をプリョジュはのに
一般的に、ビューページJSPページであった。
しかし、ダウンロードに使用されるビューは、JSPではなく、Class Fileである。
そのため、以下のように一般的に使用していたviewResolverが処理するのではなく
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="order"> <value>1</value> </property> </bean> |
tip:<property name = "order" value = "1" / >で簡単に、少なくとも構わない。
downlonadだけ処理するviewResolverが別に存在しなければならない。ここでは、id値がない( - 注意すること - )
[しかし、idをdownloadViewResolverと指定しておいたもののように使用してもされているようだ]
注: http://snoopy81.tistory.com/325
<bean id = "downloadViewResolver" class = "org.springframework.web.servlet.view .BeanNameViewResolver "> <property name= "order"> <value> 0 </value> </property> </ bean> |
tip: <property name = "order" value = "0" / > で簡単に、少なくとも構わない。
注意すべき点は、上記二つのコードに含まれているプロパティを見ると、「order」というプロパティがあり
このプロパティは、二つ以上存在するviewResolverのために 優先順位をつけることである。
優先順位は、「0」が最初に実行され、以降満たされる順序に従って実行される0〜...
次の viewResolver が実行されている基準は、「null 」 が返されるのかが基準である。
(つまり、優先順位0がnullを返すされた時、1が実行される)
そのため、Null値を持つことがない InternalResourceViewResolver が優先順位が高くなると、
他の viewResolverは 使用されなくなる問題がある。
(そのため、 BeanNameViewResolver に orderの 優先のを "0 "にしたもの。)
だから InternalResourceViewResolverは優先順位が最も低いならない。
今BeanNameViewResolver の使用方法を調べてみる。
BeanNameViewResolver(ファイルのダウンロードviewResolver) 「null」が返されない場合(つまり、コントローラクラスで戻されたビューのページの値と一致するビンいる場合) コントローラクラスから返されてきたビューページの値と一致するビン登録されている場合は、 空に対応するコントローラクラスがファイルのダウンロードを処理することになる。
そのため、コントローラクラスでviewResolverに投げ与える ビューページ名と処理するviewクラス空の名前が同じである。 (この言葉を逆に言うと、実際の jsp が示しなければならないされるとき戻り値とview空の名前が同じであって、絶対ならない。) <bean id = "download" class = "Spring.DownloadView" /> - このコードはダウンロードを処理するビュークラスを登録するものである。 そこid = "download"とされている部分と、クラスから戻された値が同じである。 そしてurlを処理するコントローラクラスも登録されるべきである。 <bean id = "down" class = "Spring.DownloadController" /> |
ここまではいくつかの複雑ですが、servlet.xmlファイルを設定する部分である。
一つ一つゆっくり読んでみると、理解できるだろう。
今、最初から一つずつ基づいてみよう。
ファイル名にリンクをかけて、コントローラクラスに渡す部分から開始
.jsp
<a href="/Spring/download.do?path=${path}&fileName=${itemBean.fileName}"> $ {itemBean.fileName} </a> |
download.doにファイル名とパスを渡す。
パスを渡し受けないならば?
(現在進行中であったプロジェクトでは、catalina.propertiesにファイルパスを入れてロードするように使用した。
後でパッチをしてくれると、パスを変更されずserverにプログラムを配布する時に、固定的にしておく機ためである。)
- 現在のプロジェクトでは、....
catalina.properties
SERVER_FILE_PATH = C:/ file_download / |
DownloadController.java
public ModelAndView download(HttpServletRequest request) throws Exception{ String filePath = System.getProperty( " SERVER_FILE_PATH "); //catalina.properties if(filePath == null || filePath.equals( "")== true){ filePath = message.getMessage( "SERVER_FILE_PATH"); //メッセージ if(filePath == null || filePath.equals( "")== true){ throw new Exception( "現在のプログラムファイルのダウンロードパスが存在しません。"); } } |
念のためにmessage.propertiesも保存置いた。
それでは本題に戻りjspのurlを処理するコントロールクラスは
<bean id = "down" class = "Spring.DownloadController" />
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @Controller public class DownloadController implements ApplicationContextAware{ private WebApplicationContext context = null; @RequestMapping("download.do") public ModelAndView download(@RequestParam("path")String path, @RequestParam("fileName")String fileName){ String fullPath = path + "\\" + fileName; File file = new File(fullPath); return new ModelAndView("download", "downloadFile", file); } @Override public void setApplicationContext(ApplicationContext arg0) throws BeansException { // TODO Auto-generated method stub this.context = (WebApplicationContext)arg0; } } | cs |
@RequestMapping( "download.do")アノテーションで指定してくれたように
download.doが入ってくるとメソッドが動作します。
リンクで与えたように、パスとファイル名を受け取って
ファイルに組み合わせて使って「download」ビューのページにファイルを "downloadFile」の名前で挿入し、戻りせる。
그 러 면 <bean class= "org.springframework.web.servlet.view.BeanNameViewResolver ">
そのviewResolverが最初にリターンを処理しようとするものである。
「download」に登録されたビンを探し見るの私たちは、さっき「download」に、ビュークラスを登録させておいた。
<bean id = "download" calss = "Spring.DownloadView" />
今DownlaodView.javaクラスがビューのページで動作するものである。
ビューページでは、mapに登録されたファイルを利用してencoding設定とヘッダの設定をしてくれた後、ファイルを指定の場所に書く。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | import java.io.File; import java.io.FileInputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.util.FileCopyUtils; import org.springframework.web.servlet.view.AbstractView; public class DownloadView extends AbstractView { public void Download(){ setContentType("application/download; utf-8"); } @Override protected void renderMergedOutputModel(Map<string, object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // TODO Auto-generated method stub File file = (File)model.get("downloadFile"); System.out.println("DownloadView --> file.getPath() : " + file.getPath()); System.out.println("DownloadView --> file.getName() : " + file.getName()); response.setContentType(getContentType()); response.setContentLength((int)file.length()); String userAgent = request.getHeader("User-Agent"); boolean ie = userAgent.indexOf("MSIE") > -1; String fileName = null; if(ie){ fileName = URLEncoder.encode(file.getName(), "utf-8"); } else { fileName = new String(file.getName().getBytes("utf-8")); }// end if; response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";"); response.setHeader("Content-Transfer-Encoding", "binary"); OutputStream out = response.getOutputStream(); FileInputStream fis = null; try { fis = new FileInputStream(file); FileCopyUtils.copy(fis, out); } catch(Exception e){ e.printStackTrace(); }finally{ if(fis != null){ try{ fis.close(); }catch(Exception e){} } }// try end; out.flush(); }// render() end; } | cs |
ここまでが
ファイルへのリンクをクラックしてダウンロードをする一連の過程をコードで解放されたものである。
注:http://winmargo.tistory.com/103
ここで、より追加するとすれば
Metis_NoticeBoardServiceController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | public ModelAndView insertBoard(HttpServletRequest request, @ModelAttribute Metis_NoticeBoardServiceParam noticeboardserviceparam ) throws Exception{ JSONObject returnObject= new JSONObject(); try{ MultipartFile file_data1 = noticeboardserviceparam.getFile_data1(); MultipartFile file_data2 = noticeboardserviceparam.getFile_data2(); MultipartFile file_data3 = noticeboardserviceparam.getFile_data3(); MultipartFile file_data4 = noticeboardserviceparam.getFile_data4(); MultipartFile file_data5 = noticeboardserviceparam.getFile_data5(); Map<String,MultipartFile> map = new HashMap<String,MultipartFile>(); if(file_data1 != null && file_data1.getSize() > 0) map.put("file_data1", file_data1); if(file_data2 != null && file_data2.getSize() > 0) map.put("file_data2", file_data2); if(file_data3 != null && file_data3.getSize() > 0) map.put("file_data3", file_data3); if(file_data4 != null && file_data4.getSize() > 0) map.put("file_data4", file_data4); if(file_data5 != null && file_data5.getSize() > 0) map.put("file_data5", file_data5); JSONObject param = parameterTransJSONObject.getJSONObject(noticeboardserviceparam); param.put("operator_ip", request.getRemoteAddr()); returnObject = metis_noticeboardscreenflow.insertBoard(param,map); }catch(Exception e) { if(returnObject.has("status") == false){ returnObject.put("status","ERROR"); } if(returnObject.has("statusDescription") == false){ returnObject.put("statusDescription","오류가 발생 했습니다."); } log4jLogManager.debug(logger, e); } request.setAttribute("result", returnObject); return new ModelAndView("/result.jsp"); } | cs |
多数のfileを受けるため MultipartFileを
Map型で入れてサービスまでファイルを送った。
(ファイルはトランザクション処理がされていないので、一番最後に処理するため)
ソースファイル名を保存すると、ファイル名の重複されて物理的に保存時に問題が発生する。
そのため、ファイル名を乱数に変更し
- 元のファイル名 |
- 拡張子 |
- ランダムファイル名 |
を作ってくれる。
originalFileName = file_data.getOriginalFilename(); originalFileExtension = originalFileName.substring(originalFileName.lastIndexOf( ".")); //.まで切り取る(拡張子を知るために) storedFileName = getRandomString()+ originalFileExtension; //ランダム文字列+拡張子
|
NoticeBoardServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | @Override @Transactional(propagation=Propagation.REQUIRED, rollbackFor={Exception.class}) public JSONObject insertBoard(JSONObject param,Map<String, MultipartFile> MultipartMap) throws Exception { File file= null; if(MultipartMap != null){ /**ストレージパス*/ String file_url = System.getProperty("SERVER_FILE_PATH"); if(file_url == null || file_url.equals("")==true){ file_url = message.getMessage("SERVER_FILE_PATH"); } //String file_url = catalina_base; //+System.getProperty("file.separator")+"download"+System.getProperty("file.separator")+"BTLMS"+System.getProperty("file.separator")+"NOTICE"+System.getProperty("file.separator"); file = new File(file_url); if(file.exists() == false){//ファイルとディレクトリが実際に存在しない場合 file.mkdirs(); //ディレクトリが作られています。 } Map<String,Object> fMap = new HashMap<String, Object>(); MultipartFile file_data =null; String originalFileName =""; String originalFileExtension=""; String storedFileName =""; Long size =null; byte[] bytes =null; for(int i=1;6>i;i++){ file_data = MultipartMap.get("file_data"+i); if(file_data != null){ originalFileName = file_data.getOriginalFilename(); originalFileExtension = originalFileName.substring(originalFileName.lastIndexOf(".")); //.まで切り取る(拡張子を知るため) storedFileName = getRandomString() + originalFileExtension;//ランダム文字列+拡張子 size = file_data.getSize(); bytes = file_data.getBytes(); fMap.put("FILE_KEY" ,noticeboardDAO.getSEQKey()); fMap.put("METIS_NOTICE_KEY" ,metis_notice_key); fMap.put("ORIGINAL_FILE_NAME",originalFileName); fMap.put("STORED_FILE_NAME" ,storedFileName); fMap.put("FILE_EXTENSION" ,originalFileExtension); fMap.put("FILE_BYTES" ,bytes.toString()); fMap.put("FILE_SIZE" ,size); fMap.put("FILE_ADDRESS" ,file_url); fMap.put("FIRST_WORK" ,first_work); noticeboardDAO.insert_file(fMap); /**ファイル添付*/ file = new File(file_url + storedFileName); file_data.transferTo(file); //ファイルコピー一時メモリを保存する file.createNewFile(); } } } return resultObject; } | cs |
このようにDBに保存してくれる。
今ダウンロードするときだ。
ダウンロードするファイルの
物理アドレスに格納されている ランダムファイル名と
既存の入力する際の 元のファイル名 を
画面で渡し受ける。
(あえてDBからオフ出さずに使用するために、フロントで送ってくれる。)
DownloadController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @RequestMapping("/fileDownload.do") public ModelAndView download(HttpServletRequest request) throws Exception { String filePath = System.getProperty("SERVER_FILE_PATH"); //catalina.properties if(filePath == null || filePath.equals("")== true){ filePath = message.getMessage("SERVER_FILE_PATH"); //message if(filePath == null || filePath.equals("")== true){ throw new Exception("現在、プログラムファイルのダウンロードパスが存在しません。"); } } File downloadFile = null; if(request.getParameter("original_file_name") != null){ /******************************************** * 元の名前に変更した後にエクスポートするときの使用(通知をダウンロード) ********************************************/ File file_original = new File(filePath+request.getParameter("original_file_name"));//原本ファイル名 File file_stored = new File(filePath+request.getParameter("stored_file_name")); //変更されたファイル名 try{ if( file_stored.exists() == true) file_stored.renameTo( file_original );//이름변경 }catch(Exception e){ throw new Exception("存在しない変更ファイル名です。"); } downloadFile = new File(filePath + request.getParameter("original_file_name")); }else{ downloadFile = new File(filePath + request.getParameter("fileName")); } return new ModelAndView("downloadView", "downloadFile", downloadFile); //バイトで送ってくれる } | cs |
File file_original = new File(filePath + request.getParameter("original_file_name")); //原本ファイル名 File file_stored = new File(filePath + request.getParameter("stored_file_name")); //変更されたファイル名
|
jspで元のファイル名と変更されたファイル名を受け
if(file_stored.exists() = = true)file_stored.renameTo(file_original); //名前変更
|
ファイルが保存された物理アドレスにランダムファイル名を元のファイル名に変更してくれる。
その後、DownloadView.javaに返させてくれる。
返す新しい のModelAndView("downloadView" 、 "downloadFile" 、downloadFileを)。 //biteで送ってくれる。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | public class DownloadView extends AbstractView { /** * */ public DownloadView() { setContentType("application/download; charset=utf-8"); } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { File file = (File)model.get("downloadFile"); response.setContentType(getContentType()); response.setContentLength((int)file.length()); String userAgent = request.getHeader("User-Agent"); boolean ie = userAgent.indexOf("MSIE") > -1; String fileName = null; if(ie) { fileName = URLEncoder.encode(file.getName(), "utf-8"); } else { fileName = new String(file.getName().getBytes("utf-8"), "iso-8859-1"); } response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";"); response.setHeader("Content-Transfer-Encoding", "binary"); OutputStream out = response.getOutputStream(); FileInputStream fis = null; try { fis = new FileInputStream(file); FileCopyUtils.copy(fis, out); } finally { if(fis != null) { try { fis.close(); } catch(IOException ioe) {} } } out.flush(); /**ダウンロード後に変更された名前を変更する */ if(request.getParameter("stored_file_name") != null){ File original_file= new File(file.getPath()); //ソースパス+ファイル String file_path = original_file.toString().replace(file.getName(),""); //path 抽出 File stored_file = new File(file_path+request.getParameter("stored_file_name"));//変更ファイル名 original_file.renameTo(stored_file);//名前変更 } } } | cs |
DownloadView処理がすべてされた後
再び元のファイル名をランダムファイル名に変更してくれる。
if(request.getParameter("stored_file_name") != null){ File original_file = new File(file.getPath()); //ソースパス+ファイル String file_path = original_file.toString().replace(file.getName()、""); //path 抽出 File stored_file = new File(file_path + request.getParameter("stored_file_name")); //変更されたファイル名 original_file.renameTo(stored_file); //名前の変更 }
|
理由は、ダウンロード時にランダムファイル名にユーザーが受けることを防止して
ダウンロードされたとき、元のファイル名に変更がされているので、重複してファイル名が一致していなくて、次回のダウンロード時に問題が生じる。
この方法では、複数のファイルを保存し、ダウンロードすることができます。
'Spring' 카테고리의 다른 글
DI(의존성 주입) (4) | 2016.11.23 |
---|---|
Environment , 프로퍼티 , 프로필 , 메시지 (0) | 2016.11.19 |
Spring EcoLibrary - Mybatis 순서 (0) | 2016.10.12 |
Spring Framework: annotation 정리 #1 (0) | 2016.09.22 |
Spring 컨테이너 및 설정 파일 (0) | 2016.07.19 |