티스토리 뷰

728x90
반응형
SMALL

파일 업로드

1.<form> 태그 이용

  • 브라우저의 제한이 없어야하는 경우에 사용.
  • 일반적으로 페이지 이동과 동시에 첨부파일을 업로드하는 방식
  • <iframe> 을 이용해서 화면의 이동 없이 첨부파일을 처리

2.Ajax를 이용

  • 첨부파일을 별도로 처리
  • <input type='file'> 을 이용하고 Ajax로 처리
  • HTML5의 Drag and Drop기능이나 jQuery라이브러리를 이용해서 처리하는 방식

파일업로드시 고려할 점

1.동일한 이름으로 업로드되었을 때 기존파일이 사라지는문제.
2.이미지파일의경우, 원본파일의 용량이 큰 경우 섬네일이미지를 생성해야 하는 문제
3.이미지파일과 일반파일을 구분해서 다운로드, 혹은 페이지에서 조회하도록 처리해야하는 문제
4.첨부파일공격에 대비하기위한 업로드파일의 확장자 제한

파일 확장자, 크기 사전 처리

var regex = new RegExp("(.*?\.(exe|sh|zip|alz)$)");
     var maxSize = 5242880;

     function checkExtension(fileName, fileSize) {
         if (fileSize >= maxSize) {
            alert("파일 사이즈 초과");
            return false;
        }
         if (regex.test(fileName)) {
            alert("해당 종류 파일은 업로드 안됨");
            return false;
        }
     }

중복된 이름 첨부파일 처리
년/월/일 폴더 생성

private String getFolder() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Date date = new Date();

        String str = sdf.format(date);

        return str.replace("_", File.separator);
    }

@PostMapping("/uploadFormAction")
public void uploadFormPost(MultipartFile[] uploadFile, Model model) {
    String uploadFolder = "C:\\upload";

    // make folder
    File uploadPath = new File(uploadFolder, getFolder());
    log.info("upload path");

    if (uploadPath.exists() == false) {
        uploadPath.mkdir();
    }

    for (MultipartFile multipartFile : uploadFile) {
        log.info("=====================================");
        log.info("Upload File Name : " + multipartFile.getOriginalFilename());
        log.info("Upload File Size : " + multipartFile.getSize());

        String uploadFileName = multipartFile.getOriginalFilename();

        uploadFileName = uploadFileName.substring(uploadFileName.lastIndexOf("\\") + 1);
        log.info("only file name : " + uploadFileName);

        File saveFile = new File(uploadPath, uploadFileName);

        try {
            multipartFile.transferTo(saveFile);
        } catch (Exception e) {
            // TODO: handle exception
            log.error(e.getMessage());
        }
    }
}

중복방지를 위한 UUID 적용

UUID uuid = UUID.randomUUID();
uploadFileName = uuid.toString() + "_" + uploadFileName;

섬네일 이미지 생성

1.pom.xml 추가

<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.8</version>
</dependency>

2.UploadController에 단계별 추가

  • 업로드된 파일이 이미지 종류의 파일인지 확인
  • 이미지파일의 경우에는 섬네일이미지 생성 및 저장
// 이미지타입인지 검사하는 checkImageType메서드 생성
private boolean checkImageType(File file) {
    try {
        String contentType = Files.probeContentType(file.toPath());

        return contentType.startsWith("image");
    } catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
    }
    return false;
}

3.UploadController에 해당 내용 추가

try {
    File saveFile = new File(uploadPath, uploadFileName);

    multipartFile.transferTo(saveFile);
    if (checkImageType(saveFile)) {
        FileOutputStream thumnail = new FileOutputStream(new File(uploadPath, "s_" + uploadFileName));

        Thumbnailator.createThumbnail(multipartFile.getInputStream(), thumnail, 100, 100);
        thumnail.close();
    }
} catch (Exception e) {
    // TODO: handle exception
    log.error(e.getMessage());
}

브라우저에 별도의 객체를 생성해서 처리하기 위해 jackson-databind 관련 라이브러리 추가

1.pom.xml에 관련 라이브러리 추가

<!-- jackson-databind -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.9.5</version>
</dependency>

2.AttachfileDTO 클래스 생성

  • AttachfileDTO 클래스의 내용
import lombok.Data;

@Data
public class AttachFileDTO {

    private String fileName;
    private String uploadPath;
    private String uuid;
    private boolean image;
}
  • UploadController에서 AttachFileDTO의 리스트를 반환하는 구조로 변경
@PostMapping(value = "/uploadAjaxAction", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public ResponseEntity<List<AttachFileDTO>> uploadAjaxPost(MultipartFile[] uploadFile) {
    List<AttachFileDTO> list = new ArrayList<AttachFileDTO>();
    String uploadFolder = "c:\\upload";

    String uploadFolderPath = getFolder();

    // make folder
    File uploadPath = new File(uploadFolder,uploadFolderPath);

    if (uploadPath.exists() == false) {
        uploadPath.mkdir();
    }
    // make yyyy/mm/dd folder

    for (MultipartFile multipartFile : uploadFile) {
        AttachFileDTO attachDTO = new AttachFileDTO();

        String uploadFileName = multipartFile.getOriginalFilename();

        uploadFileName = uploadFileName.substring(uploadFileName.lastIndexOf("\\") + 1);
        log.info("only file name : " + uploadFileName);

        attachDTO.setFileName(uploadFileName);

        UUID uuid = UUID.randomUUID();
        uploadFileName = uuid.toString() + "_" + uploadFileName;

        try {
            File saveFile = new File(uploadPath, uploadFileName);

            multipartFile.transferTo(saveFile);

            attachDTO.setUuid(uuid.toString());
            attachDTO.setUploadPath(uploadFolderPath);

            if (checkImageType(saveFile)) {

                attachDTO.setImage(true);

                FileOutputStream thumnail = new FileOutputStream(new File(uploadPath, "s_" + uploadFileName));

                Thumbnailator.createThumbnail(multipartFile.getInputStream(), thumnail, 100, 100);
                thumnail.close();
            }

            // add list
            list.add(attachDTO);

        } catch (Exception e) {
            // TODO: handle exception
            log.error(e.getMessage());
        }
    }
    return new ResponseEntity<List<AttachFileDTO>>(list, HttpStatus.OK);
}
  • 해당 jsp파일 수정
$.ajax({
    url: '/uploadAjaxAction',
    processData: false,
    contentType: false,
    data: formData,
    type: 'POST',
    dataType: 'json',
    success: function(result) {
        console.log(result);
    }
});
728x90
반응형
LIST

'Spring boot study > 7. 파일업로드' 카테고리의 다른 글

브라우저에서 섬네일 처리  (0) 2020.08.14
댓글
반응형
250x250
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
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
글 보관함