프로젝트에서 이미지 파일을 압축하고 webp로 변환하여 서버로 전송하도록 했다. 분명 file.type이 image/webp가 되는 걸 확인했는데 서버에서 받은 이미지 URL에는 원본 파일의 확장자가 적용되어 있었다.
import Compressor from 'compressorjs';
export async function compressImage(
file: File,
quality: number = 0.8,
): Promise<File> {
return new Promise((resolve, reject) => {
new Compressor(file, {
quality,
mimeType: 'image/webp',
maxWidth: 880,
maxHeight: 620,
success(result) {
const compressedFile = new File([result], file.name);
resolve(compressedFile);
},
error(err: Error) {
console.error(err.message);
reject(err);
},
});
});
}
이런 형태의 compressor를 사용하고 있었고, mimeType을 설정해 두었기 때문에 서버에 webp 포맷의 파일이 전송될 줄 알았다. 무엇이 문제인가 했더니 file.name에 원본 파일 확장자가 포함되어 있었고, 서버에서 file.type보다 file.name의 확장자를 더 우선시해서 발생한 일이었다.
const newFileName = file.name.replace(/\.[^/.]+$/, '.webp');
...
success(result) {
const webPFile = new File([result], newFileName);
resolve(webPFile);
},
file.name에 포함된 확장자를 webp로 대체한 후, webp 파일이 서버에 업로드된 걸 확인할 수 있었다.
비슷한 이슈로, file URL → File 변환을 구현해야 했다. file.type을 ‘application/pdf’, ‘image/png’ 등으로 설정해서 파일의 타입을 세팅하는 것이라 생각하고 있었는데 filename이 중요한 것이었다.
export const convertURLtoFile = async (
url: string,
filename: string,
options?: { type?: string; headers?: AxiosRequestConfig['headers'] },
) => {
try {
const response = await axios.get(url, {
responseType: 'blob',
withCredentials: true,
headers: options?.headers || {},
});
const blob = response.data;
return new File([blob], filename, { type: options?.type ?? blob.type });
} catch (error) {
console.log('파일 변환 실패 : ', error);
throw error;
}
};
blob.type이 URL(파일)의 확장자 정보를 가지고 있을 줄 알고 filename을 확장자 없이 이름만 받아오도록 했다. 그런데 blob.type이 application/octet-stream이어서 확장자가 없는 파일이 생성되었다.
File URL에서 파일 확장자를 추출하고, 이를 포함한 filename을 넘기니 정상적으로 파일 변환이 이루어졌다.
const ext = getFileExtension(fileUrl);
const file = convertURLtoFile(fileUrl, `result.${ext}`);
MIME 타입과 file name의 확장자를 모두 맞추는 게 신뢰성에는 더 좋겠지만, 우리가 구현한 파일 변환과 같이 다양한 포맷의 파일이 입력으로 들어올 수 있는 경우 이에 맞는 MIME 타입 값을 설정하는 것이 쉽지 않다. 일반적인 경우에는 파일명에 포함된 확장자로도 충분히 처리가 가능하다고 한다. 우리 팀도 단순히 클라우드 저장소에 File 업로드, File Url - File 변환만 하고 있기 때문에 파일명만 확장자를 포함해 설정하기로 했다.
파일 이름이라고 하면 확장자 앞 문자열로만 느껴졌는데, 확장자가 포함되며 중요하게 여겨진다는 것을 알게 되었다!
'Study > TIL · 오류해결' 카테고리의 다른 글
AWS S3 CORS 문제 해결하기 (+ 브라우저 캐시 문제) (0) | 2024.09.25 |
---|---|
[TIL] 프론트엔드, 백엔드 도메인이 다를 때 쿠키 설정 (0) | 2024.09.12 |
vite.config.js에서 환경 변수 사용하기 (0) | 2024.09.05 |
[Next.js] 서버 컴포넌트 try-catch에서 redirect가 안 된다 (0) | 2024.08.16 |
[TypeScript/Jest] jest.setup.js를 설정했는데도 jest-dom 타입 오류가 뜨는 문제 (0) | 2024.08.14 |