logo

파일 업로드 프론트엔드 구현

2020. 01. 07.

프론트단 파일업로드를 구현하는도중 여러 파일을 선택하고 관리하기위해 input type=file을 제어하는 소스코드를 생성해보았다.

 

원리는 버튼 하나에 input file을 겹쳐놓아 한개 씩 파일 업로드를 받고 업로드가 완료되면 새 input file 태그를 복제해 기존 태그위에 겹쳐놓는다. 그러면 버튼은 새로 복제된 비어있는 input file에 또 적재하게되는 원리이다.

 

일반적으로는 input file 태그를 추가하는 방식으로 기존에 많이 이용한 부분을 좀 직관적인 ui로 변경해본 케이스이다.

아래 예제코드로 파일을 넘기게 되면 $_FILES['REQ_FILE'] 배열에 순차적으로 파일이 넘어오게된다.

 

 

아직까진 실험적인 부분이 많습니다. (한번에 다중파일 선택은 제어해야할 변수가 너무 많아서 일단 보류)

 

update.php

1
2
3
4
5
6
7
8
<div class="btn-file-upload">
  <div class="btn btn-block theme-green">
    <span>파일 선택</span>
    <input type="file" id="REQ_FILE" name="REQ_FILE[]">
  </div>
  <small class="form-text text-muted">확인 버튼을 눌러야 선택한 파일이 업로드 됩니다.</small>
</div>
 
cs

 

script-file.js

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
$(function(){
  // 파일 업로드 제어
  let counter = 0;
  $('#REQ_FILE').on('change'function(e) {
    if (e.target.files.length > 0) {
      let newId = $(this).prop('id'+ '_' + counter++;
      let file = $(this).prop('files')[0];
      let fileName = encodeURIComponent(file.name); // 한글 파일명 대응
      let fileSize = file.size;
      let uri = '/ajax/file-list.php?file_name=' + fileName + '&file_size=' + fileSize + '&input_file=' + newId;
      // 파일 리스트 추가 및 삭제 이벤트 할당
      $('.file-list').append($('<li class="pending">').load(uri, function() {
        $(this).find('.btn-cancel-file').first().on('click'function() {
          let id = $(this).data('id');
          $(id).remove();
          $(this).closest('li').remove();
        });
      }));
      // 파일폼 복제 후 새 파일폼으로 교체. 나중에 추가된(비어있는) 폼이 우선적으로 선택됨
      $(this).after($(this).clone(true).val(''));
      $(this).prop('id', newId);
    }
  });
  
  // 파일 삭제
  $('.file-list .btn-file-remove').on('click'function() {
    if (confirm('정말로 삭제하시겠습니까?')){
      let action = 'remove-file';
      let key = $(this).data('key');
      let list = $(this).closest('li');
      $.post('_update.php', {ACTION: action, REQ_KEY: key}, function(data) {
        if (data === 'done') {
          list.remove();
        } else {
          alert('삭제처리 도중에 문제가 발생했습니다.');
        }
      });
    }
  });
  
});
 
cs

 

ajax/file-list.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
$file_name = $_GET['file_name'];
$file_size = $_GET['file_size'];
$input_file = $_GET['input_file'];
?>
 
<hr>
<div class="d-flex align-items-center">
  <span class="file-icon"><?= get_icon_by_extension($file_name?></span>
  <div class="file-info">
    <div class="file-name"><?= $file_name ?></div>
    <span class="file-size"><?= number_format($file_size / 10485762) . ' MB' ?></span>
    <span class="file-date">업로드 대기 중</span>
  </div>
  <div class="file-func">
    <a href="#" class="btn-cancel-file" data-id="#<?= $input_file ?>"><i class="fas fa-fw fa-times"></i></a>
  </div>
</div>
 
cs

 

실제 적용 화면

 

MySQL GROUP_CONCAT 기능으로 쿼리 결과를 하나로 합치기

MySQL GROUP_CONCAT 기능으로 쿼리 결과를 하나로 합치기

2019. 09. 03.
Mysql CONCAT 기능에 대해서

Mysql CONCAT 기능에 대해서

2019. 09. 03.
Nginx 특정 IP 차단 하기

Nginx 특정 IP 차단 하기

2019. 06. 20.
로그 더 보기