본문 바로가기
Back-end/JAVA & Spring

[Java] 파일 다운로드 - 2가지 방식

by 꼬바리 2022. 4. 19.

 😎방법 1 - response Flush

더보기
@Controller
public class CommonController {
     
    @Resource(name="commonService")
    private CommonService commonService;
     
    @RequestMapping(value="/common/downloadFile.do")
    public void downloadFile(CommandMap commandMap, HttpServletResponse response) throws Exception{
        Map<String,Object> map = commonService.selectFileInfo(commandMap.getMap());
        String original_File_Name = (String)map.get("ORIGINAL_FILE_NAME");
        String stored_File_Name = (String)map.get("STORED_FILE_NAME");
         
        byte[] fileByte = FileUtils.readFileToByteArray(new File("C:\\dev1\\file\\"+stored_File_Name));
        
        //파일유형설정
        response.setContentType("application/octet-stream"); 
        //파일길이설정
        response.setContentLength(fileByte.length);
        //데이터형식/성향설정 (attachment: 첨부파일)
        response.setHeader("Content-Disposition", "attachment; fileName=\"" + URLEncoder.encode(original_File_Name,"UTF-8")+"\";");
        //내용물 인코딩방식설정
        response.setHeader("Content-Transfer-Encoding", "binary");
        //버퍼의 출력스트림을 출력
        response.getOutputStream().write(fileByte);
        
        //버퍼에 남아있는 출력스트림을 출력
        response.getOutputStream().flush();
        //출력스트림을 닫는다
        response.getOutputStream().close();
 
    }
}

[HttpServletResponse response]

HTTPServletResponse파라미터로 서버에서 client로 응답할 때 사용하는것으로, 파일을 client에게 전송할때 사용한다.

 

[response.setContentType()]

파일유형을 설정해 줍니다.

웹서버는 브라우저로 전송될 페이지가 html인 경우 text/html을 표준 MIME타입으로 지정합니다.

MIME타입을 변경 또는 인코딩셋을 변경하고자 할때, setContentType메소드를 사용합니다.

octet-stream은 8비트 바이너리배열을 의미하며, http나 email상에서 application이 지정되지 않았거나 형식을 모를때 사용합니다.

즉, 브라우저는 octet-stream으로 MIME타입이 지정된 경우 바이너리 데이터로만 다운로드가 가능하게됩니다.

 - HTML로 출력시 : setContentType("text/html");

 - 일반 TEXT로 출력시 : setContentType("text/plain");

 - 이미지 GIF로 출력시 : setContentType("image/gif");

 - 이미지 JPG, JPEG로 출력시 : setContentType("image/jpeg");

 - PDF로 출력시 : setContentType("???");

 

[response.setHeader("Content-Disposition", "attachment; fileName=~~~;]

Content-Disposition은 HTTP Response Body에 오는 컨텐츠의 기질/성향을 알려주는 속성입니다.

Default값은 inline으로 웹에 전달되는 data라고 생각하면 됩니다.

Content-Disposition에 attachment를 주는 경우, Body에 오는 값을 다운로드 받으라는 뜻입니다.

attachment는 첨부파일을 의미합니다. fileName은 다운로드할때의 파일이름을 의미합니다. UTF-8인코더는 한글변환을 위함입니다.

attachment;와 fileName 사이에는 띄워쓰기를 꼭 해주어야 하고 인코드하는 뒤 부분 "\" 부분도 꼭 써줘야 다운로드가 가능합니다.

 

[response.setHeader("Content-Transfer-Encoding", "binary")]

Content-Transfer-Encoding 는 전송되는 데이터의 안의 내용물들의 인코딩 방식을 말합니다. 여기에선 binary 방식입니다.

 

[response.getOutputStream().write(fileByte)]

byte[]타입으로 변환한 파일을 reponse를 통해 client로 보내줍니다.

Stream은 데이터의 입력과 출력을 하도록 이어주는 통로입니다.

Stream은 데이터를 보낼때 '임시적으로 모아서 보내줍니다.' 여기서 임시로 모아두는 공간이 buffer입니다.

파일에 data를 쓸때 buffer에 내용을 채운 후 파일에 쓰게됩니다.

 

[response.getOutputStream().flush();]

reponse를 중지합니다.

flush는 버퍼를 비우는 기능을 합니다.

연속적으로 data를 쓸 경우 buffer가 차게되면, 자동으로 flush해준 후 다음 내용을 buffer에다 채우게 됩니다.

남아있는 내용을 buffer에 채웁니다.

 

[response.getOutputStream().close();]

reponse를 닫아줍니다.

close함수 내부적으로 flush함수를 호출하기때문에 flush함수를 안써도됩니다.

 

 

 

😎방법 2 - ResponseEntity

더보기
@GetMapping("download/file")
	public ResponseEntity<?> downloadWdAgreeFile(HttpServletRequest request) throws Exception {
		
		loggerService.insertInLog(request);
		
		String uri = request.getRequestURI();
		HashMap<String, Object> param = RequestUtil.paramToHashMap(request);
		String viewTf = StringUtil.fixNull(param.get("view")); 
		String pm = request.getHeader("client-id");
		param.put("uri", uri);
		param.put("client-id", pm);
		
		LuluResult result = wdAgreeService.getWdAgreeApplyAttathFile(param);
		
		if(!LuluResultUtil.checkSuccess(result)) return LuluResponse(result);
		
		String fileName = (String) JsonUtil.toHashMapObject(JsonUtil.toJson(result.getResultData())).get(CommCode.WD_ATCH_FILENM);
		byte[] file = Base64.getDecoder().decode(JsonUtil.toHashMapObject(JsonUtil.toJson(result.getResultData())).get(CommCode.WD_ATCH_FILE).toString());
		
		loggerService.insertOutLog(request, result);
		
		HttpHeaders header = new HttpHeaders();
		
		if("".equals(viewTf) || "F".equals(viewTf)) {
			header.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+fileName);
			header.add("Cache-Control", "no-cache, no-store, must-revalidate");
	        header.add("Pragma", "no-cache");
	        header.add("Expires", "0");
		} else if("T".equals(viewTf)) {
			header.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename="+fileName);
		}
        
        ByteArrayResource resource = new ByteArrayResource(file);
        
        String ext = fileName.substring(fileName.indexOf(".") + 1);
        if("pdf".equals(ext)) {
	    	 return ResponseEntity.ok()
	                 .headers(header)
	                 .contentLength(file.length)
	                 .contentType(MediaType.parseMediaType("application/pdf"))
	                 .body(resource);
        } else if("jpg".equals(ext) || "jpeg".equals(ext)) {
        	return ResponseEntity.ok()
	                 .headers(header)
	                 .contentLength(file.length)
	                 .contentType(MediaType.parseMediaType("image/jpeg"))
	                 .body(resource);
        } else {
        	return ResponseEntity.ok()
	                 .headers(header)
	                 .contentLength(file.length)
	                 .contentType(MediaType.parseMediaType("application/octet-stream"))
	                 .body(resource);
        }
+ Java Byte[] TO File (바이트배열에서 파일로 저장)

바이트 배열을 파일로 저장해야할때 사용합니다.

DB에 있는 blob 이미지를 파일로 저장할때 사용했습니다.

아래 함수를 이용하여 사용하시면 됩니다.

public void writeToFile(String filename, byte[] pData)

{

    if(pData == null){

        return;

    }



    int lByteArraySize = pData.length;

    System.out.println(filename);



    try{

        File lOutFile = new File("C:/Users/madev/Downloads/test/"+filename);

        FileOutputStream lFileOutputStream = new FileOutputStream(lOutFile);

        lFileOutputStream.write(pData);

        lFileOutputStream.close();

    }catch(Throwable e){

        e.printStackTrace(System.out);

    }

}

 

 

 

728x90
반응형

댓글