게시판 - 글 수정 새로 파일첨부하기

이태현·2025년 9월 15일

Web 개발

목록 보기
47/53
post-thumbnail

Frontend

  // 수정 - 새로운 파일 첨부
  const id_attach = document.querySelector("#id_attach")

  if (id_attach) {
    id_attach.addEventListener("change", () => {
      const f = new FormData()

      f.append("bcode", params['bcode']) // 게시판 코드
      f.append("mode", "file_attach") // 모드 : 파일만 첨부
      f.append("idx", params['idx'])

      if (id_attach.files[0].size > 40 * 1024 * 1024) {
        alert("파일 크기가 40MB보다 큰 파일이 첨부되었습니다.")
        id_attach.value = ""
        return false
      }

      ext = getExtensionOfFilename(id_attach.files[0].name)
      if (ext == 'exe' || ext == 'php' || ext == 'js') {
        alert("첨부할 수 없는 파일을 업로드 하였습나다. (exe, txt, xls, php, js ..)")
        id_attach.value = ""
        return false
      }
      f.append("files", id_attach.files[0])

      const xhr = new XMLHttpRequest()

      xhr.open('post', './pg/board_process.php', true)
      xhr.send(f)

      xhr.onload = () => {
        if (xhr.status = 200) {
          alert('통신 성공')
        } else if (xhr.status == 404) {
          alert('통신 실패')
        }
      }
    })
  }

기존에 게시글 작성 부분을 가져와 수정하였습니다. 크게 설명할 부분이 없어서 생략하도록 하겠습니다.

Backend

Ajax

  if (id_attach) {
    id_attach.addEventListener("change", () => {
      const f = new FormData()

      f.append("bcode", params['bcode']) // 게시판 코드
      f.append("mode", "file_attach") // 모드 : 파일만 첨부
      f.append("idx", params['idx'])

      if (id_attach.files[0].size > 40 * 1024 * 1024) {
        alert("파일 크기가 40MB보다 큰 파일이 첨부되었습니다.")
        id_attach.value = ""
        return false
      }

      ext = getExtensionOfFilename(id_attach.files[0].name)
      if (ext == 'exe' || ext == 'php' || ext == 'js') {
        alert("첨부할 수 없는 파일을 업로드 하였습나다. (exe, txt, xls, php, js ..)")
        id_attach.value = ""
        return false
      }
      f.append("files[]", id_attach.files[0])

      const xhr = new XMLHttpRequest()

      xhr.open('post', './pg/board_process.php', true)
      xhr.send(f)

      xhr.onload = () => {
        if (xhr.status = 200) {
          const data = JSON.parse(xhr.responseText)
          if (data.result == 'success') {
            location.reload()
          } else if (data.result == 'empty_files') {
            alert('파일이 첨부되지 않았습니다.')
          }
        } else if (xhr.status == 404) {
          alert('통신 실패')
        }
      }
    })
  }

원래는 Frontend 부분에서 파일을 저장할 때 files 변수에 저장하려고 했는데 그렇게 하면 방식을 바꿔야 해서 배열로 받기로 하였습니다. 물론 바꾸지 않는다고 해서 안 되는 건 아닙니다. 단지 지금 여태까지 사용해 오던걸 사용하기 위함입니다.

board_process.php

else if ($mode == 'file_attach') {
  // 수정에서 개별파일 첨부하기

  $file_list_str = '';
  if (isset($_FILES["files"])) {
    $file_cnt = 1;
    $file_list_str = $board->file_attach($_FILES['files'], $file_cnt);
  } else {
    $arr = ['result' => 'empty_files'];
    die(json_encode($arr));
  }

  $row = $board->view($idx);

  if ($row['files'] != '') {
    $files = $row['files'] . '?' . $file_list_str;
  } else {
    $files = $file_list_str;
  }

  if ($row['downhit'] != '') {
    $downs = $row['downhit'] . '?0';
  } else {
    $downs = '';
  }
  $board->updateFileList($idx, $files, $downs);
  $arr = ['result' => 'success'];
  die(json_encode($arr));
}

게시글을 작성할 때 파일을 첨부하지 않을 수도 있기 때문에 비어 있을 때를 대비하였습니다.
기존에 파일이 있거나 다운로드 횟수가 존재하면 그대로 새로운 파일만 '?' 을 추가해 주고 다운로드 횟수 또한 값이 존재하면 거기에 '?0' 을 붙여주었습니다. 값이 비어 있을 때는 그대로 두었습니다.

Board Class

  // 파일 첨부
  public function file_attach($files, $file_cnt,)
  {
    if (sizeof($files["name"]) > 3) {
      $arr = ["result" => "file_upload_count_exceed"];
      die(json_encode($arr));
    }

    // 다중 파일 첨부

    $tmp_arr = [];
    foreach ($files["name"] as $key => $val) {
      $full_str = "";
      $tmparr = explode(".", $files["name"][$key]);
      $ext = end($tmparr);

      $not_allowed_file = ["exe"];
      if (in_array($ext, $not_allowed_file)) {
        $arr = ["result" => "not_allowed_file"];
        die(json_encode($arr));
      }

      $flag = rand(1000, 9999);
      $filename = 'a' . date('YmdHis') . $flag . '.' . $ext;
      $file_ori = $files["name"][$key]; // 원본 이미지
      copy($files["tmp_name"][$key], BOARD_DIR . '/' . $filename); // 이미지 파일 저장
      $full_str = $filename . '|' . $file_ori; // 원본 이미지 이름과 바뀐 이미지 이름
      $tmp_arr[] = $full_str;
    }
    return implode("?", $tmp_arr);
  }

기존에 사용하는 방식을 바꾸었습니다. 원래는 다중으로 파일을 업로드 할 수 있었는데, 하나씩 첨부하는 거로 수정하였습니다. 수정하는 부분에서 파일을 업로드 할때 이미 2개의 파일이 존재할 때 2개 이상 파일을 올리게 되면 파일 개수를 넘어섭니다. 그러면 또 거기서 1개를 받든 2개를 받든 해야 하는데 그렇게 되면 너무 로직이 복잡해져서 등록할 때는 multiple로 3개까지 등록을 허용하되, 수정할 때는 한 개씩 등록하도록 하였습니다. 그래서 파일을 첨부하고 확인을 눌렀을 때 등록되는 게 아니라 첨부파일이 변화를 감지했을 때, 즉 파일을 선택한 순간 바로 첨부되는 구조로 하였습니다. 그리고 게시글 작성할 때나 수정할 때 사용하기에 Board Class로 빼서 공용으로 사용하였습니다.

마무리

다음 시간에는 글 수정을 하여 DB에 저장하는 부분을 해보겠습니다.

감사합니다.

profile
이해하고 분석하고 지배한다

0개의 댓글