JavaScript

form에 이미지 파일 전송하기

hojomu 2023. 9. 21. 09:28

form 태그에 이미지 파일과 text 데이터를 담은 json을 넣어서 php 서버로 request 하고 response를 받아보자

 

1. 이미지 파일 업로드, 변수에 저장하기

-> 일반적인 문자, 숫자와 다르게 이미지, 동영상 등의 미디어 파일이나 json 형태의 데이터를 원본 그대로 전송하고 싶다면, blob 객체로 만들어서 전송해야한다.

 

<input type="text" name="Text1" id="text1"> 
<input type="text" name="Text2" id="text2">
<input type="file" name="Img" id="userImg" accept="image/*" multiple>

이미지를 가져오려면 input에 file 타입을 선언하고 파일의 형식을 accept에 지정해줘야한다.

multiple 속성을 선언하면 여러개의 파일을 가져올 수 있다.

 

const text1 = document.querySelector("#text1");
const text2 = document.querySelector("#text2");
const userImg = document.querySelector("#userImg");

let selectedImages;

userImg.addEventListener("change", function() {
selectedImages = userImg.files;

    for (let i = 0; i < selectedImages.length; i++) {
        let selectedImage = selectedImages[i];
        if (!selectedImage.type.startsWith('image/')) {
            alert('이미지 파일만 업로드할 수 있습니다.');
            userImg.value = '';
            return;
        }
    }
}

userImg,files를 이용하면 userImg 태그에 있는 파일들을 모두 가져올 수 있다. 각각의 파일들은 객체로 되어있다

 

2. form 태그 작성 및 XMLHttpRequest 보내기

Btn.addEventListener("click", function(e) {
      e.preventDefault();
      
      let xmlHttpRequest = new XMLHttpRequest();
      
      // response 처리용 함수
      xmlHttpRequest.onreadystatechange = function() {
        try {
          if (xmlHttpRequest.readyState === 4) {
            if (xmlHttpRequest.status === 200) {
              console.log('response 성공');
            } else {
              console.log('response 실패');
            }
          }
        } catch (e) {
          console.log('Caught Exception: ' + e.description);
        }
      };
      
      // form 작성
      const form = new FormData();
      form.append('userImg', selectedImages[0]);
      const stringDataDto = JSON.stringify({
        text1: text1.value,
        text2: text2.value
      });
      form.append('stringDataDto', new Blob([stringDataDto], {
        type: 'application/json'
      }));
      
      xmlHttpRequest.responseType = 'blob';
      xmlHttpRequest.open('POST', 'Img.php', true);
      xmlHttpRequest.send(form);
}

-> XMLHttpsRequest를 전송하고 받으려면, onreadystatechange 이벤트를 가진 함수를 선언해야한다.

request를 전송한 다음 response를 받으면 해당 함수를 실행한다.

또 js에서 form을 생성했는데, 이미지와 같은 file 이나 json같은 데이터를 전송하고싶다면 blob 과 같은 객체 형태로 변경해서 type을 지정해서 보낼 수 있다.

request의 바디에는 다음과 같이 WebKitForm 내부에 blob 형태의 json과 image/png 가 들어가있는 것을 확인할 수 있다.

 

3. php에서 response 보내기

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $imgFilePath = $_FILES['userImg']['tmp_name'];
    $stringDataDto = $_FILES['stringDataDto']['tmp_name'];
    
    $stringData = file_get_contents($stringDataDto);
    $img = imagecreatefrompng($imgFilePath);
    
    //
    파일 처리
    //
    
    header("Content-Type: image/jpeg");
    imagepng($img);
    imagedestroy($img);
}

request를 post 방식으로 전송했기 때문에, php에서 $_SERVER 슈퍼 변수에 REQUEST_METHOD가 어떤건지 확인한다.

 

$_FILES 변수에 request body에 담았던 파일들이 임시파일로 저장되어 있기 때문에, 임시파일의 경로로 부터 파일을 저장해서 사용할 수 있다.

 

php에서 echo나 print_r 등의 출력 함수를 사용하면, response에 담겨서 나가게 되는데, 위와 같이 img 처럼 특정 확장자의 파일을 response 하고싶으면, header 에 타입을 꼭 지정해 줘야한다.