ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Next.js의 api ruoter로 cors우회하기3(with 파일데이터)
    카테고리 없음 2024. 8. 10. 00:04

    지난번 포스팅에서는 api rotuer에서 파일데이터를 다루는법을 포스팅하겠다. 

    post요청을 할때 이미지를 formData를 통해 보낼 수가 있는데 page router는 formData를 처리하는 기능이 없다. 

    app router는 있지만 page rotuer는 없어서 약간의 편법을 사용하도록 하겠다. 

     

    먼저 formData부분을 JSON으로 변경해야햔다. 

    다른데이터들은 상관이 없지만 파일 데이터는 약간의 변형이 필요하다. 

     images: {
              file: await Promise.all(values.images.map(async image => await getBase64(image as File))),
              fileName: values.images.map((image: unknown) => (image as File).name),
            },

    파일과 파일이름을 각각 따로 보내주어야 한다. 

    파일이름은 파일 객체에서 File.name부분을 추출해서 배열로 담아주고 파일은 파일객체가 아닌 문자열로 변환해 주어야 한다. 

     

    File 객체를 문자열로 변환하는 이유는 JSON으로 넘어갈 때 파일이 깨쳐서 api router에서 File추출이 되지 읺는다. 

    그래서 getBase64라는 util함수를 만들고 getBase64를 통해 파일을 문자열로 변환하여 api router에 전송한다. 

     

    getBase64

    function getBase64(file: File) {
      return new Promise<string>((resolve, reject) => {
        const reader = new FileReader();
    
        reader.readAsDataURL(file);
        reader.onload = () => resolve(<string>reader.result);
        reader.onerror = error => reject(error);
      });
    }

     

    그 다음 api url에 쿼리스트링으로 ?dataType=formData을 작성한다. 

    ?dataType=formData을 작성하면 해당 요청을 파일을 갖고있는 요청이라고 조건을 걸어서 파일을 위한 처리를 따로 하려고 한다. 

     

    api router에서 file처리

    먼저 if문으로 파일처리를 위한 axios요청을 따로 만든다. 

      const { dataType } = req.query as { dataType: string };
    
    if (dataType === 'formData') {
    	...
    }

    req.query는 ?뒤에오는 쿼리스트링을 가져오는 메서드 이다. 

    dataType이라는 쿼리스트링을 가져오고 if문으로 dataType이 formData인 api요청만 따로 처리한다. 

     

    formData 객체를 만들고 body값을 for문으로 순회하면서 formData를 추가한다. 

    body값은 객체이기때문에 객체의 키 밸류를 순화하는 for in문을 사용한다. 

    const formData = new FormData();
          for (const key in body) {
            if (
              (body[key].file || body[key].fileName) &&
              (typeof body[key].file === 'object' || typeof body[key].fileName === 'object')
            ) {
              const base64Data = body.images.file.map((image: string) => image.replace(/^data:image\/\w+;base64,/, ''));
              const buffer = base64Data.map((base64: string) => Buffer.from(base64, 'base64'));
              formData.append('thumbnail', buffer[0], { filename: body.images.fileName[0] });
              buffer.forEach((image: Buffer, index: number) =>
                formData.append(`images[${index}]`, image, { filename: body.images.fileName[index] }),
              );
           
            } else {
              formData.append(key, body[key]);
            }
          }

    다른건 뒤로하고 file부분만 작성하겠다

     

    코드설명

    문자열로 되어있는 파일 데이터를 buffer로 변환하기 위해 문자열에서 필요없는 부분을 삭제한 후 brffer로 변환한다. 데이터는 배열로 되어있기 때문에 map method를 사용하여 변환한다.

     

    그다음 formData에 append하면 되는데 썸네일과 이미지를 따로 저장하기 때문에 api문서데로 로직을 구현하였다. 

     

    그이후는 이전 포스팅에서 axios에 객체를 인자로 넣어서 사용하는 방법을 하면 된다. 

          const config = {
            method,
            url: `${process.env.NEXT_PUBLIC_SERVER_BASE_URL}${url ? url : urlInQueryString}`,
            headers: {
              Authorization: `Bearer ${session.accessToken}`,
              refreshToken: `${session.refreshToken}`,
              ...formData.getHeaders(),
            },
            data: formData,
          };
          console.log(formData);
          const response = await axios(config);
          res.status(200).send(response.data);
          return;
Designed by Tistory.