[Spring] 파일 업로드 다운로드

hyewon jeong·2024년 2월 2일
0

Spring

목록 보기
52/65

파일업로드 다운로드를 공부하면서 짠 로직이다.

1. 파일 업로드

1-1. 파일 업로드 폼 작성법- jsp

<form action = "upload" method = "post" encrytype = "multipart/form-data">
	<div>
    	<label for = "title" > 제목 </label>
        <input type = "text" name = "title", id = "title"/>
    </div>
    <div>
    	<label for  = "myFile"> 첨부파일</ label>
        <input type ="file" name = "myFile" id = "myFile"/>
    </div>
    <button type ="submit"> 업로드</button>
</form>    
 
  • form 태그 안에 input 요소로 받은 정보를 button submit에 의해 서버로 전송된다.

1-2. 파일 업로드 폼 작성법 - js

var FormData = new FoamData();이용

  • html이 아닌 자바스크립트단에서 form 전송 동작이 필요한 경우가 있는데 , 이미지와 같은 멀티미디어 파일 페이지를 전환없이 폼데이터를 비동기로 제출하고 싶을때나 , 자바스크립트로 좀 더 타ㅣ이트하게 폼데이터를 관리하고 싶을 때 사용하는 객체 이다.
  • FormData() 객체는 자바스크립트에서 다루는 객체로, html에서의 태그와 동일한 역을 한다.
  form.append('키','값'):
  • append 로 key:value값을 붙이면 input에 name:value 와 같은 효과를 지닌다.
  if($('#버튼요소id').val()){
     var formData = new FormData();
     formData.append('files',document.getElementById('파일이 담기는 요소 아이디').files[0];

<input type = "file">
<input type = "file"> 일 경우 파일은 리스트로 저장되어 , 하나의 파일을 선택할 경우 .files[0] 로 파일을 선택한다.

1-3. 파일 업로드 서버단

/**
	 *
	 * @param multipartFile ajax를 통해 클라이언트로 부터 전달 받은 파일
	 * @param params 필요한 매개변수
	 * @return
	 */
	public Map<String,Object> fileUpload(MultipartFile multipartFile, Map<String,Object> params) throws IOException {
		String pathName = "/file/upload";
		Map<String,Object> resultMap = new HashMap<>();
		resultMap.put("result",false);

		if(!multipartFile.isEmpty()){
        //Spring에서 제공하는 cleanPath()를 통해서 ../ 내부 점들에 대해서 사용을 억제한다
		   String fileName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
		   boolean ck = ckFileExtensions( fileName);
				if(ck== true){
					//throw new CustomException(BAD_FILE_EXT);
				}
			}

		File dir = new File(pathName); // 1.업로드한 파일을 저장할 디렉토리를 만듬
		if(!dir.exists()){
			boolean t = dir.mkdirs();
			if(t == true){
				System.out.println("디렉토리가 정상적으로 만들어졌습니다.");
			}else{
				System.out.println("디렉토리 생성에 실패했습니다.");
			}
		}
		// 디렉토리 권한 설정
		dir.setExecutable(true,true); // 실행 setExecutable(boolean executable, boolean ownerOnly)
		dir.setReadable(true);// 읽기 setReadable(boolean readable)
		dir.setWritable(true,true);// 쓰기 setWritable(boolean writable, boolean ownerOnly)


		//2. multifile에서 받은 파일을 해당디렉토리에 있는 파일에 넣기 위해 해당 경로에 파일 생성
		String uuid = UUID.randomUUID().toString().replaceAll("-","");
		File file = new File(dir.getAbsolutePath()+File.separator+ uuid);
		boolean t1 = file.createNewFile();
		if(t1 == true){
			System.out.println("파일이 정상적으로 만들어졌습니다.");
		}else{
			System.out.println("파일 생성에 실패했습니다.");
		}

		Map<String,Object> fileSn = // 디비에서 파일명만 가져온다.
		if(fileSn != null){
			try{
				multipartFile.transferTo(file); // 생성한 파일에 업로드한 파일을 전달한다.
				resultMap.put("result",true);
			}catch(IOException e ){
				System.out.println(e.getMessage());
				throw new CustomException();
			}
		}

		return resultMap;
	}
	public boolean ckFileExtensions( String fileName){
		String[] permissibleExtension = {"jpg","jpeg","png","zip","pdf","gif"};
		int extLength = permissibleExtension.length;
		String ext = fileName.substring(fileName.lastIndexOf(".")+1,fileName.length());
		for(int i = 0; i < extLength ;i++){
			if(ext.equalsIgnoreCase(permissibleExtension[i])){
				return false; // 허용된 확장자일때 false
			}
		}
        return true;
    }

2. 파일 다운로드

2-1.파일 다운로드 - jsp

<a href="download?num=${tmp.num }">${tmp.orgFileName }</a>

2-2.파일 다운로드 - js

  $('<form action = "'+url +'" method = "'+method '" 
           target ="' accept-charset = "UTF-8" >'+'</form>')
    .appendTo('body').submit().remove();
  • 제이쿼리를 이용하여 form데이터 폼을 생성하여 body에 붙인후 제출 -> 해당 form을 제거한다.

2-3.파일 다운로드 서버단

	public void fileDownLoad (HttpServletRequest request, HttpServletResponse response, Map<String,Object> params) throws IOException {

		String fileName = (String) params.get("fileName");
		String fileSn = (String) params.get("fileSn");
		if(fileName == null || fileSn == null ){
			return;
		}
		// 1.fileName,fileSn 을 통해 디비에서 해당 파일의 정보를 가져온다.
		String exampleFileNm = "test.jpg";
		String uploadPath = "download/file";
        String realFileNm = "AAA_202401232433424.jpg"
		String path = uploadPath + File.separator + exampleFileNm;

		File file = new File(path); // 패스에 해당하는 파일을 생성한다.
		
		FileInputStream fis = null;
		fis = new FileInputStream(file); // 화면에 표시하고자 하는 파일을 바이트로 입력받아 바이트 단위로 출력할 수 있는 클래스
		byte[] bytes = new byte[4098]; // 읽어올 파일을 일정한 크기로 잘라 담기 위한 바이트 버퍼
		BufferedInputStream bis = new BufferedInputStream(fis);  //BufferedInputStream 이용하여 파일을 읽어올때  8192 버퍼를 두고 작업하기 때문에 속도가 굉장히 빠르다. 그래서 파일크기가 8192 넘지 않는다면 무조건 쓰는게 좋음
		ServletOutputStream fos = response.getOutputStream(); // 파일다운로드를 위해 생성된 파일을 스트림에 파일데이터를 쓰면 httpServletResponse객체를 통해 http 응답 바디에 전달되어 브라우저가 flush()의해 파일이 출력되고 버퍼는 비워진다.
		BufferedOutputStream bos = new BufferedOutputStream(fos);
     // 응답헤더 설정 
    //한글 파일명 세부처리 
          String encodedName = null;
	      if(request.getHeader("User-Agent").contains("Firefox")){
	         //벤더사가 파이어 폭스인경우 
	         encodedName=new String
	            (realFileNm.getBytes("utf-8"),"ISO-8859-1");
	      }else{ //그외 다른 벤더사 
	         encodedName=URLEncoder.encode(realFileNm, "utf-8");
	         //파일명에 공백이있는 경우 처리 
	         encodedName=realFileNm.replaceAll("\\+"," ");
	      }
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedName + "\";");
        response.setHeader("Content-Type", application/octet-stream);
		try{ //파일을 쪼개는 이유는 네트워크 통로가 좁기때문에 일렬로 작은단위(패킷)들이 넘어와 저장할때 조합이 되고 , 이것을 스트림이라 한다.

			int inputData = 0;
			while((inputData = bis.read(bytes)) != -1){
				bos.write(inputData);
				bos.flush();
			}

			// 파일 다운로드 로직
		}catch(IOException e){
			System.out.println(e.getMessage());
		}finally{
			if(fis !=null){
				fis.close();
			}
			if(bis !=null){
				bis.close();
			}
			if(fos !=null){
				fos.close();
			}
			if(bos !=null){
				bos.close();
			}
		}

	}

FileInputStream

파일 내용 화면 출력FileInputStream 는 InputStream 를 상속받았으며, 파일로 부터 바이트로 입력받아, 바이트 단위로 출력할 수 있는 클래스이다. FileInputStream 를 생성할 수 있는 방법으로는 다음 같이 존재한다

브라우저별 한글 파일명 인코딩하기(엣지 추가)

profile
개발자꿈나무

0개의 댓글