본문 바로가기

카테고리 없음

spring --10.파일 업로드 상세 처리

A> 정규식을 이용한 파일 확장자 체크

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var regex = new RegExp("(.*?)\.(exe|sh|zip|alz)$");
var maxSize = 5242880; //5MB
 
function checkExtension(fileName, fileSize){
  
  if(fileSize >= maxSize){
    alert("파일 사이즈 초과");
    return false;
  }
  
  if(regex.test(fileName)){
    alert("해당 종류의 파일은 업로드할 수 없습니다.");
    return false;
  }
  return true;
}
 
cs

 

B> 중복된 이름 파일 처리

spring --9. 에 있음

 

a> UUID를 이용한 고유한 문자열 생성

1.  매년,매월,매일로 구분한 디렉토리 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 private String getFolder() {
 
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
 
    Date date = new Date();
 
    String str = sdf.format(date);
 
    return str.replace("-", File.separator);
  }
 
그 후에

 File uploadPath = new File(uploadFolder, getFolder());
 log.info("upload path: " + uploadPath);
 
 
cs

 

2.UUID 로 파일 중복 없애기

1
2
3
4
5
6
7
8
9
10
11
12
13
UUID uuid = UUID.randomUUID();
 
        uploadFileName = uuid.toString() + "_" + uploadFileName;
 
        File saveFile = new File(uploadPath, uploadFileName);
 
        try {
 
         multipartFile.transferTo(saveFile); //저장 폴더에 저장
        } catch (Exception e) {
          log.error(e.getMessage());
        } // end catch
 
cs

 

 

C> 섬네일 이미지 생성

1. pom.xml 에 추가

1
2
3
4
5
6
<dependency>
      <groupId>net.coobird</groupId>
      <artifactId>thumbnailator</artifactId>
      <version>0.4.8</version>
 </dependency>
 
cs

 

2.섬네일 처리 단계

a> 이미지 여부 판단

.

1
2
3
4
5
6
7
8
9
10
try {
      String contentType = Files.probeContentType(file.toPath());
 
      return contentType.startsWith("image");
 
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
 
cs

b> 섬네일 생성

1
2
3
4
5
6
7
8
9
10
 if (checkImageType(saveFile)) {
 
              FileOutputStream thumbnail = 
                new FileOutputStream(new File(uploadPath, "s_" + uploadFileName));
 
              Thumbnailator.createThumbnail(multipartFile.getInputStream(), thumbnail, 100100);
 
              thumbnail.close();
            }
 
cs

 

D> 브라우저에서의 ajax 처리

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$.ajax({
      url: '/uploadAjaxAction',
      processData: false, 
      contentType: false,
      data: formData,
         type: 'POST',
         dataType:'json',
         success: function(result){
    
           console.log(result);
    
         }
    }); //$.ajax 
 
cs

 

E> 섬네일 띄우기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 $.ajax({
        url : '/uploadAjaxAction',
        processData : false,
        contentType : false,
        data : formData,
        type : 'POST',
        dataType : 'json',
        success : function(result) {
 
          console.log(result);
 
          showUploadedFile(result);
 
          $(".uploadDiv").html(cloneObj.html());
 
        }
      }); //$.ajax
 
 
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
 function showUploadedFile(uploadResultArr) {
 
      var str = "";
 
      $(uploadResultArr).each(function(i, obj) {
 
        str += "<li>" + obj.fileName + "</li>";
 
      });
 
      uploadResult.append(str);
    }
 
cs

 

F> 이미지 다운로드

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
31
32
33
34
35
36
37
38
39
40
41
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    @ResponseBody
    public ResponseEntity<Resource> downloadFile(@RequestHeader("User-Agent") String userAgent, String fileName) {
 
        Resource resource = new FileSystemResource("c:\\upload\\" + fileName);
 
        if (resource.exists() == false) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
 
        String resourceName = resource.getFilename();
 
        // remove UUID
        String resourceOriginalName = resourceName.substring(resourceName.indexOf("_") + 1);
 
        HttpHeaders headers = new HttpHeaders();
        try {
 
            String downloadName = null;
 
            if ( userAgent.contains("Trident")) {
                log.info("IE browser");
                downloadName = URLEncoder.encode(resourceOriginalName, "UTF-8").replaceAll("\\+", " ");
            }else if(userAgent.contains("Edge")) {
                log.info("Edge browser");
                downloadName =  URLEncoder.encode(resourceOriginalName,"UTF-8");
            }else {
                log.info("Chrome browser");
                downloadName = new String(resourceOriginalName.getBytes("UTF-8"), "ISO-8859-1");
            }
            
            log.info("downloadName: " + downloadName);
 
            headers.add("Content-Disposition", "attachment; filename=" + downloadName);
 
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
 
        return new ResponseEntity<Resource>(resource, headers, HttpStatus.OK);
    }
cs

29 라인의 ISO-8859-1 은 크롬에서 쓰는 형식

34 라인처럼 header에 추가해서 전달

 

G> 첨부파일의 삭제

1. 첨부파일 생성, 제거시 발생하는 문제점 최소화 하기 위해

    Quartz 라이브러리 사용

- Quartz 라이브러리 : 주기적으로 작업을 처리 하기 위한 라이브러리

                              -db에 있는 첨부파일 목록과 실제 업로드 폴더의 목록을 주기적으로 비교

  

2. 추가해야 할 라이브러리들

a. quartz 

b. quartz-jobs

 

3.root-context  에 설정해야 하는 것

1
2
xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.3.xsd


<task:annotation-driven />
cs

 

4.cron 설정

--시간 단위의 값을 조정

   0       *         *       *          *        *       (*) 

  초      분       시      날        달     매주     년 

0~59   0~59   0~23  1~31    1~12   1~7    optional 

 

5.컨트롤러에서의 사용 예시

 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
private String getFolderYesterDay() {
 
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
 
        Calendar cal = Calendar.getInstance();
 
        cal.add(Calendar.DATE, -1);
 
        String str = sdf.format(cal.getTime());
 
        return str.replace("-", File.separator);
    }
 
    @Scheduled(cron = "0 0 2 * * *") //매달 매일 매2시 마다
    public void checkFiles() throws Exception {
 
        log.warn("File Check Task run.................");
        log.warn(new Date());
        // file list in database
        List<BoardAttachVO> fileList = attachMapper.getOldFiles();
 
        // ready for check file in directory with database file list
        List<Path> fileListPaths = fileList.stream()
                .map(vo -> Paths.get("C:\\upload", vo.getUploadPath(), vo.getUuid() + "_" + vo.getFileName()))
                .collect(Collectors.toList());
 
        // image file has thumnail file
        fileList.stream().filter(vo -> vo.isFileType() == true)
                .map(vo -> Paths.get("C:\\upload", vo.getUploadPath(), "s_" + vo.getUuid() + "_" + vo.getFileName()))
                .forEach(p -> fileListPaths.add(p));
 
        log.warn("===========================================");
 
        fileListPaths.forEach(p -> log.warn(p));
 
        // files in yesterday directory
        File targetDir = Paths.get("C:\\upload", getFolderYesterDay()).toFile();
 
        File[] removeFiles = targetDir.listFiles(file -> fileListPaths.contains(file.toPath()) == false);
 
        log.warn("-----------------------------------------");
        for (File file : removeFiles) {
 
            log.warn(file.getAbsolutePath());
 
            file.delete();
 
        }
    }
cs