파일업로드 다운로드를 공부하면서 짠 로직이다.
<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.append('키','값'):
if($('#버튼요소id').val()){
var formData = new FormData();
formData.append('files',document.getElementById('파일이 담기는 요소 아이디').files[0];
<input type = "file">
<input type = "file">
일 경우 파일은 리스트로 저장되어 , 하나의 파일을 선택할 경우 .files[0] 로 파일을 선택한다.
/**
*
* @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;
}
<a href="download?num=${tmp.num }">${tmp.orgFileName }</a>
$('<form action = "'+url +'" method = "'+method '"
target ="' accept-charset = "UTF-8" >'+'</form>')
.appendTo('body').submit().remove();
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 는 InputStream 를 상속받았으며, 파일로 부터 바이트로 입력받아, 바이트 단위로 출력할 수 있는 클래스이다. FileInputStream 를 생성할 수 있는 방법으로는 다음 같이 존재한다