게시판 - 글 수정 첨부파일삭제

이태현·2025년 9월 12일

Web 개발

목록 보기
46/53
post-thumbnail

첨부파일 삭제

<?php

include "inc/common.php";
include "inc/dbconfig.php";
include "inc/board.php";

$bcode = isset($_GET["bcode"]) && $_GET["bcode"] != "" ? $_GET["bcode"] : "";
$idx = isset($_GET["idx"]) && $_GET["idx"] != "" ? $_GET["idx"] : "";

if ($bcode == "") {
  die('
  <script>
  alert("게시판 코드가 누락되었습니다.")
  history.back()
  </script>');
}
if ($idx == "") {
  die('
  <script>
  alert("게시물 번호가 누락되었습니다.")
  history.back()
  </script>');
}

// 게시판 목록 불러오기
include "inc/boardmanage.php";
$boardm = new BoardManage($db);
$boardArr = $boardm->list();
$board_name = $boardm->getBoardName($bcode);

// 게시판
$board = new Board($db);
$boardRow = $board->view($idx);

// $_SERVER['REMOTE_ADDR'] : 사용자가 현재 페이지를 보고있는 IP 주소입니다.
if ($boardRow['last_reader'] != $_SERVER['REMOTE_ADDR']) {
  $board->hitINC($idx);
  $board->updateLastReader($idx, $_SERVER['REMOTE_ADDR']);
}

// 다운로드 횟수 저장 배열
$downhit_arr = explode('?', $boardRow['downhit']);
if ($boardRow['id'] != $ss_id) {
  die('
  <script>
  alert("본인의 게시물이 아닙니다. 수정할 수 없습니다.")
  location.href="./board.php?bcode=' . $bcode . '"
  </script>');
}

$boardRow['content'] = str_replace('`', '\`', $boardRow['content']);

$js_array = ['js/board_edit.js'];
$g_title = "게시판";

include "inc_header.php";
?>

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/summernote@0.9.0/dist/summernote-lite.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.9.0/dist/summernote-lite.min.js"></script>

<main class="w-75 mx-auto border rounded-2 p-5">
  <h1 class="text-center">게시물 수정</h1>

  <div class="mb-2">
    <input type="text" name="subject" id="id_subject" class="form-control" value="<?= $boardRow['subject']; ?>" placeholder="제목을 입력해 주세요." autocomplete="off">
  </div>
  <div id="summernote"></div>

  <div class="mt-3">
    <?php

    if ($boardRow['files'] != '') {

      $filelist = explode('?', $boardRow['files']);

      $th = 0;
      foreach ($filelist as $file) {
        list($file_source, $file_name) = explode('|', $file);
        if ($boardRow['downhit'] == '') {
          // [배열명] = array_fill([시작번호], [채울 항목 수], '[값]');
          $downhit_arr = array_fill(0, count($filelist), 0);
        }
        echo "<a href=\"./pg/boarddownload.php?idx=$idx&th=$th\">$file_name</a> 
        <button class='btn btn-danger btn-sm mb-2 btn_file_del' data-th='" . $th . "'>삭제</button><br>";
        $th++;
      }
    }
    ?>

  </div>

  <div>
    <input type="file" name="attach" id="id_attach" class="mt-2 form-control" multiple>
  </div>

  <div class="mt-2 d-flex gap-2 justify-content-end">
    <button class="btn btn-primary" id="btn_write_submit">확인</button>
    <button class="btn btn-secondary" id="btn_board_list">목록</button>
  </div>

</main>

<script>
  $('#summernote').summernote({
    placeholder: '내용을 입력해 주세요.',
    tabsize: 2,
    height: 400,
    toolbar: [
      ['style', ['style']],
      ['font', ['bold', 'underline', 'clear']],
      ['color', ['color']],
      ['para', ['ul', 'ol', 'paragraph']],
      ['table', ['table']],
      ['insert', ['link', 'picture', 'video']],
      ['view', ['fullscreen', 'codeview', 'help']]
    ]
  });
  var markupStr = `<?= $boardRow['content']; ?>`
  $('#summernote').summernote('code', markupStr);
</script>

<?php
include "inc_footer.php";
?>

기존에 있던 글 쓰기 페이지를 가지고 수정하였습니다. 해당 첨부 파일을 삭제하기 위해서 삭제 버튼을 하나 추가하였습니다. 버튼을 구분하기 위해서 첨부파일의 순서 값을 주었습니다.

JS

// URL 쿼리 스트링 가져오기
function getURLParams() {
  const params = {}

  window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi,
    function (str, key, value) {
      params[key] = value
    })
  return params
}

document.addEventListener('DOMContentLoaded', () => {
  const params = getURLParams()
  const btn_file_dels = document.querySelectorAll(".btn_file_del")

  btn_file_dels.forEach((box) => {
    box.addEventListener('click', () => {

      if (!confirm('해당 파일을 삭제하시겠습니까?')) {
        return false
      }
      const th = box.dataset.th
      const bcode = params['bcode']

      const f = new FormData()
      f.append("bcode", bcode) // 게시판 코드
      f.append("idx", params['idx'])
      f.append("th", th)
      f.append("mode", "each_file_del") // 모드 : 개별 파일 삭제

      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 == 'empty_idx') {
            alert('게시물 번호가 누락되었습니다.')
          } else if (data.result == 'empty_th') {
            alert('몇번째 첨부파일인지 알 수가 없습니다.')
          } else if (data.result == 'success') {
            alert('파일이 정상적으로 삭제되었습니다.')
            location.reload()
          }
        } else if (xhr.status == 404) {
          alert('파일이 없습니다.')
        }
      }
    })
  })
})
  1. 삭제 버튼의 요소를 담아서 클릭 이벤트를 만듭니다.
  2. Ajax 통신을 하기 위해 값들을 설정하여 통신할 페이지에 값을 넘겨줍니다.
    ex) bcode, idx, th, mode
  3. 통신 결과에 맞게 조건을 주었습니다.

게시판 Class

  // 첨부파일 삭제 이후 이미지 문자열, 다운로드횟수 문자열 재조합
  public function updateFileList($idx, $files, $downs)
  {
    $sql = "UPDATE board SET files=:files, downhit=:downhit WHERE idx=:idx";
    $stmt = $this->conn->prepare($sql);
    $params = [":idx" => $idx, "files" => $files, "downhit" => $downs];
    $stmt->execute($params);
  }

변경된 값을 DB에 저장합니다.

게시판 Process

else if ($mode == 'each_file_del') {
  if ($idx == '') {
    $arr = ['result' => 'empty_idx'];
    die(json_encode($arr));
  }
  if ($th == '') {
    $arr = ['result' => 'empty_th'];
    die(json_encode($arr));
  }
  $file = $board->getAttachFile($idx, $th);

  $each_files = explode('|', $file);
  // BOARD_DIR . '/' . $each_files[0])
  if (file_exists(BOARD_DIR . '/' . $each_files[0])) {
    unlink(BOARD_DIR . '/' . $each_files[0]);
  }

  $row = $board->view($idx);
  // 이미지 문자열 재조합
  $files = explode('?', $row['files']);
  $tmp_arr = [];
  foreach ($files as $key => $val) {
    if ($key == $th) {
      continue;
    }
    $tmp_arr[] = $val;
  }
  $files = implode('?', $tmp_arr); // 새로 조합된 파일 리스트 문자열
  // 다운로드 횟수 재조합
  $tmp_arr = [];
  $downs = explode('?', $row['downhit']);
  foreach ($downs as $key => $val) {
    if ($key == $th) {
      continue;
    }
    $tmp_arr[] = $val;
  }
  $downs = implode('?', $tmp_arr); // 새로 조합된 다운로드 횟수 리스트 문자열
  $board->updateFileList($idx, $files, $downs);
  $arr = ['result' => 'success'];
  die(json_encode($arr));
  1. 해당 첨부파일을 DB에서 가져옵니다.
  2. 가져온 첨부파일을 '|' 기준으로 배열에 나누어서 담아줍니다.
    ex) a202509120854343453.jpg|lake-7938396_640.jpg
  • [0] => a202509120854343453.jpg
  • [1] => lake-7938396_640.jpg
  1. 파일이 존재할 때는 해당 위치에 파일을 삭제합니다.
    ex) BOARD_DIR . '/' . $each_files[0])
  2. idx값과 일치하는 값을 DB에서 가져와서 file 필드에 들어있는 값을 '?'기준으로 나눠줍니다.
  3. 빈 배열을 하나 만들고 가져온 file 필드에 개수만큼 반복해서 돌아주는데 해당 첨부 파일과 반복문의 key 값이 같을 경우 해당 반복문을 더 이상 수행하지 않고 다음에 반복문을 수행하여 빈 배열에 file 필드에 있는 값들을 담아줍니다.
  4. 삭제된 파일을 제외한 나머지 파일들을 다시 '?' 기준으로 재조합하여 저장합니다.
  5. 첨부파일 다운로드 조회수도 마찬가지로 삭제된 파일을 제외한 나머지 다운로드 조회수를 재조합하여 저장합니다.
  6. 새로운 첨부파일과 다운로드 조회수를 DB에 저장합니다.

결과




마무리

다음 시간에는 수정 페이지에서 새로운 첨부파일을 추가하도록 하겠습니다.

감사합니다.

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

0개의 댓글