<label htmlFor="file">파일 업로드</label> <input id="file" onChange={handleFileChange} />
<label htmlFor="file">파일 업로드</label> <input id="file" onChange={handleFileChange} />
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => { if (!e.target.files) return; const formData = new FormData(); // key가 file0, file1, ...인 form 필드의 value에 파일 정보를 담아 formData에 추가한다. // 서버에서 파일을 구별하기 위해 key를 이런 식으로 설정한다. for (let i = 0; i < e.target.files.length; i++) { formData.append(`file${i}`, e.target.files[i]); } // POST 요청 postImages(formData); };
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => { if (!e.target.files) return; const formData = new FormData(); // key가 file0, file1, ...인 form 필드의 value에 파일 정보를 담아 formData에 추가한다. // 서버에서 파일을 구별하기 위해 key를 이런 식으로 설정한다. for (let i = 0; i < e.target.files.length; i++) { formData.append(`file${i}`, e.target.files[i]); } // POST 요청 postImages(formData); };
// 인수로 받은 formData를 body에 담아 POST 요청한다. const postImages = async (formData: FormData) => { await fetch("http://localhost:4000/image", { method: "POST", body: formData, }); };
// 인수로 받은 formData를 body에 담아 POST 요청한다. const postImages = async (formData: FormData) => { await fetch("http://localhost:4000/image", { method: "POST", body: formData, }); };
const fileData = await new Promise((resolve, reject) => { const form = new formidable.IncomingForm(); // formidable로 폼 파싱 form.parse(req, (err, fields, files) => { if (err) return reject(err); return resolve({ fields, files }); }); }); const parsedFileData = fileData;
const fileData = await new Promise((resolve, reject) => { const form = new formidable.IncomingForm(); // formidable로 폼 파싱 form.parse(req, (err, fields, files) => { if (err) return reject(err); return resolve({ fields, files }); }); }); const parsedFileData = fileData;
// parsedFileData { fields: {}, files: { file0: [ [PersistentFile] ], file1: [ [PersistentFile] ] } }
// parsedFileData { fields: {}, files: { file0: [ [PersistentFile] ], file1: [ [PersistentFile] ] } }
fs.createReadStream()
함수로 WriteStream
객체로 만들고 업로드하기Object.values(parsedFileData.files).forEach(async item => { // fs.createReadStream이용해 스트림 전환 후 올리기 const fileBuffer = fs.createReadStream(item[0].filepath); fileBuffer.on('error', err => console.log(err)); const fileName = item[0].originalFilename; await uploadFile(fileBuffer, fileName, item[0].mimetype); });
Object.values(parsedFileData.files).forEach(async item => { // fs.createReadStream이용해 스트림 전환 후 올리기 const fileBuffer = fs.createReadStream(item[0].filepath); fileBuffer.on('error', err => console.log(err)); const fileName = item[0].originalFilename; await uploadFile(fileBuffer, fileName, item[0].mimetype); });
async function uploadFile(fileBuffer, fileName, mimetype) { const uploadParams = { Bucket: awsS3Bucket, Key: fileName, Body: fileBuffer, ContentType: mimetype, }; const res = await s3.send(new PutObjectCommand(uploadParams)); return res.$metadata.httpStatusCode; }
async function uploadFile(fileBuffer, fileName, mimetype) { const uploadParams = { Bucket: awsS3Bucket, Key: fileName, Body: fileBuffer, ContentType: mimetype, }; const res = await s3.send(new PutObjectCommand(uploadParams)); return res.$metadata.httpStatusCode; }
const [images, setImages] = useState<string[]>(); const fetchDataAndSetState = () => { getImages().then(res => setImages(res)); }; ... return ( <label htmlFor="file">파일 업로드</label> <input id="file" onChange={e => { handleFileChange(e).then(() => setTimeout(() => fetchDataAndSetState(), 500)); }} multiple type="file" /> ... )
const [images, setImages] = useState<string[]>(); const fetchDataAndSetState = () => { getImages().then(res => setImages(res)); }; ... return ( <label htmlFor="file">파일 업로드</label> <input id="file" onChange={e => { handleFileChange(e).then(() => setTimeout(() => fetchDataAndSetState(), 500)); }} multiple type="file" /> ... )
파일 업로드 후 즉시 S3에 객체의 업로드가 반영이 안되기 때문에 setTimeout
함수로 시간 설정 후 fetchDataAndSetState
함수 호출한다.
로컬 스토리지, 세션 스토리지, 쿠키의 차이점을 알기 쉽게 페이지 및 API를 따로 구현했다. 프론트엔드에서 fetch 요청 시 옵션으로 credentials: "include"를
2023-08-08해시된 password를 사용하지 않았다. 로그인을 하면 jwt.sign()을 이용하여 토큰을 발급한다. - 웹 스토리지 : JWT를 브라우저에 전달한다. - 쿠키 : 서버에서 쿠
2023-08-08퍼블릭화한 S3 버킷의 객체 URL은 https://[버킷명].s3.[버킷리전].awazonaws.com/[객체]로 되어있다. ex) https://doromo-example.s3
2023-07-27Node.js와 express로 백엔드를 구축했다. 백엔드에서 aws-sdk를 이용하여 버킷과 객체에 접근할 것이다. MY_AWS_ACCESS_KEY : IAM 설정에서 발급받은
2023-07-27# Contact : jyw966@naver.com
Copyright © doromo. All Rights Reserved.