JAVA

BLOB 이미지파일업로드

docc 2021. 7. 27. 11:01

출력과 다운

1. 프로필사진 출력하기

(DB에 blob로 저장된 이미지 꺼내는 버전//이름저장하여 로컬경로로 가져오는 케이스가 아님)

>> Profile.java(Controller)

@Controller
public class Profile{

	@Autowired
	IMemberDAO memberDAO;
	
	@RequestMapping("profile/{no}")
	public void process(HttpServletRequest request, HttpServletResponse response, @PathVariable int no) {
		
		Member member = memberDAO.findByNo(no);
		byte[] profile = (byte[])member.getProfile();
		response.setContentType("image/jpeg");

		ServletOutputStream os;
		try {
			//' http규격응답' 이 클라이언트에게 보낼 상자("image/jpeg")를 
			// outputstream 에게 주면서 거기에 바이트단위의 profile의 내용물을 단위마다 write()하며 집어넣게 한다.
			// flush() : write() 시 단위까지 집어넣으면 client 에게 보내는데 못미쳐 남은 마지막껏 까지 집어넣게 하는 메서드다.
			// 안써도 작업끝나고 어느 순간에는 보내기 때문에 바로보내고 싶다 할 때 아니면 생략가능하다.
			os = response.getOutputStream();
			os.write(profile);
			os.flush();
		}catch(Exception e) {
			e.printStackTrace();
		}
		
	}
}

2. 첨부파일(Attach) 다운받게 업로드 하기

(DB에 이미지를 blob가 아닌 이름과 사이즈만 저장한 경우)

>> 게시물상세창.jsp - 업로드받을 파일 a태그

	<c:if test="${not empty board.attachs}">
	첨부 : <br />
		<ul>
		<c:forEach var="attach" items="${board.attachs}" varStatus="status">
			<li> <a href="/board/attach/${attach.no}">${attach.name} ${attach.size}</a></li>
		</c:forEach>
		</ul>
	</c:if>

>> AttachDAO

	@Override
	public Attach findByNo(int 첨부번호) {
		Connection connection = null;
		Statement 명령전달자 = null;
		Attach attach = null;
		
		try {
			connection = ConnectionUtil.getConnection();
			명령전달자 = connection.createStatement();

			
			String 수집SQL = String.format("select * from attach where no = %d",첨부번호);
			ResultSet 수집된표관리자 = 명령전달자.executeQuery(수집SQL);

			
			if(수집된표관리자.next()) {
				int no = 수집된표관리자.getInt("no");
				String name = 수집된표관리자.getString("name");
				long size = 수집된표관리자.getLong("size");
				int board_no = 수집된표관리자.getInt("board_no");
				Board board = new Board();
				board.setNo(board_no);
				
				attach = new Attach();
				attach.setNo(no);
				attach.setName(name);
				attach.setSize(size);
				attach.setBoard(board);
			}

			수집된표관리자.close();
			명령전달자.close();
			connection.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		return attach;
	}

>> Attach컨트롤.java(new)

@Controller
public class Attach컨트롤 {

	@Autowired
	IAttachDAO attachDAO;

	@RequestMapping("board/attach/{a_no}")
	public void process(HttpServletRequest request, HttpServletResponse response, @PathVariable("a_no") int 첨부번호) {
		
		try {
			 Attach attach=attachDAO.findByNo(첨부번호);
		     String filename = attach.getName();
		     String encodedFilename="";
		     
		     /*파일명이 제대로 다운로드 되지 않는 이유는
		     브라우저별로 Content-Disposition의 값에 대한
		     인코딩 처리 방식에 약간의 차이가 있어서 입니다.

		     브라우저별로 문자열처리를 하셔야
		     정상적인 파일로 다운로드가 가능합니다.
		     https://www.egovframe.go.kr/home/qainfo/qainfoRead.do?menuNo=69&qaId=QA_00000000000016942
		     */
		     String browser = request.getHeader("User-Agent"); //현재 쓰는 브라우저 알아내기
		     System.out.println(browser);
		     
		     //MSIE = 익스플로러, Chrome = 크롬, Filefox = 파이어폭스, Opera = 오페라
		     //파일이름에 utf-8 속성을 달아준다.(브라우저마다 법칙이 달라서 if문으로 다르게 넣었다. 이 부분은 깊이 생각말기)
		     if (browser.contains("MSIE")||browser.contains("Chrome")) {
		     encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");
		     } else if (browser.contains("Firefox")) {
		     encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
		     } else if (browser.contains("Opera")) {
		     encodedFilename = "\"" + new String(filename.getBytes("UTF-8"), "8859_1") + "\"";
		     }
		     String path = request.getSession().getServletContext().getRealPath("/upload/board");
		     String fullFilePath=path+"\\"+attach.getBoard().getNo()+"\\"+attach.getName();
			
			
			// 1번.
			response.setContentType("application/octer-stream: charset=utf-8");//바이너리형식
			response.setHeader("Content-Transfer-Encoding", "binary");
			response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFilename+"\"");
			File file = new File(fullFilePath);
			response.setHeader("Content-Length", "" +file.length());
			
			// 2번.
			OutputStream os = response.getOutputStream();
			
			// 3번.
			FileInputStream fis = new FileInputStream(file);
			int 읽은크기 = 0;
			byte[] 버퍼 = new byte[1024];//프로그래머가 대략 정해야함
			
			// inputStream 이 반복하여 HDD 파일을 읽어 버퍼에 데이터를 넣고 있다.
			// 한번에 넣는게 아니라 여러번 쪼개 넣음, 다 읽으면 -1 이 나옴
			while((읽은크기 = fis.read(버퍼)) != -1) {
				// outputStream 이 '버퍼' 에서 0부터 inputStream '읽은크기' 만큼 write()하고 있다.
				os.write(버퍼, 0, 읽은크기);
			}
			
			fis.close();
			os.close();
		}catch(Exception e) {
			e.printStackTrace();
		}
		
	}
1번. 파일 내용을 읽은 거 위에 헤더를 따로 붙여야 하니 response 로 binary 이며 charset=utf-8로 하며 파일이름이 이렇다 하고 지정

response.setHeader : 파일의 정보를 미리 설정해 알려준다 (데이터유형, 종류, 길이, 주소, 이름 등)
POST 방식 : Header 부분을 url 으로 하여 다운받게 할 수도 있다.
하지만 url 길이에 제한이 있어서 정보를 집어넣기만 하는 방식으로 한다.
2번. outputStream 이 그 헤더가 담긴 상자를 response 에게서 받아 inputStream 이 read()할 때 write() 한다.
3번. byte[] 형으로 메모리에 올라간 파일이 아니니 inputStream 으로 읽어야 함