이벤트 객체의 FileList는 배열이 아닌 file 객체를 여러개를 담고 있는 유사배열 객체(Array-like)이다. 위처럼 이벤트 핸들러에서 input엘리먼트의 .files로 FileList 배열객체를 참조할 수 있다.
그렇기 때문에 .files[0]접근이나 .length는 사용가능하나, 배열이 아니기 때문에 map, filter, foreach 등을 사용할 수 없는 것이다.
라고 하신다.
일단 나는 FileList를 사용하여 여러장을 올려볼 생각이다.
<Array<File>> 타입으로도 가능할 것 같긴 하다.. ㅋㅋ..
일단 Front 부터 볼까요?
먼저 html 입니다.
<input
type="file"
className="form-control mb-3"
id="inputGroupFile02"
multiple
onChange={selectFile}
/>
타입은 file
그리고 multiple 형식이 들어갔네요!!
multiple을 사용하게 되면 이런식으로 여러장을 선택할 수 있게 해줍니다.
이번엔 javascript 부분을 보시죠
const navigate = useNavigate();
// todo: 현재 선택한 파일을 저장할 배열변수
const [selectedFiles, setSelectedFiles] = useState<FileList>();
const [showImages, setShowImages] = useState([]);
// todo : 파일 선택상자에서 이미지 선택시 실행되는 함수
// 파일 선택상자 html 태그 : <input type="file" />
const selectFile = (event: any) => {
// 화면에서 이미지 선택시 저장된 객체 : event.target.files
// 변수명 as 타입명 : 개발자가 변수가 무조건 특정타입이라고 보증함
// (타입스크립트에서 체크 안함)
setSelectedFiles(event.target.files as FileList);
console.log(selectedFiles);
// Todo : 이미지 미리보기 형식
const imageLists = event.target.files;
let imageUrlLists = [...showImages];
for (let i = 0; i < imageLists.length; i++) {
const currentImageUrl = URL.createObjectURL(imageLists[i]);
(imageUrlLists as any).push(currentImageUrl);
}
if (imageUrlLists.length > 7) {
imageUrlLists = imageUrlLists.slice(0, 7);
}
setShowImages(imageUrlLists);
};
const upload = () => {
if (selectedFiles) {
ProjectsService.upload(selectedFiles)
.then((response: any) => {
navigate("/admin");
})
.catch((error: Error) => {
console.log(error);
});
}
};
보셔야 될부분은 이정도이네요!!
먼저 selectFiles 함수입니다.
이 함수는 fileList 타입 객체에 file 배열을 만들어 줍니다.
showImages 는 file의 배열이 들어가는데 요 밑의 html 로 이미지를 preview 할 수 있습니다.
한마디로 value == url 이 들어가네요!
물론 7장 제한을 걸어놯습니다. 다만 진짜 파일이 들어갈 곳은 않넣었다는 사실.. ㅋㅋ
{showImages
.map((url, index) => (
<div key={index} className="col-3 ">
<img src={url} alt="Landing Page" />
</div>
))}
네 그럼 이번에는 axios 부분을 볼까요?
이 부분은 중요합니다.
# util/http-common.ts
import axios from 'axios';
export default axios.create({
baseURL: "http://localhost:8000/api",
headers: {
"Content-Type": "application/json",
}
});
# service/service.ts
const upload = (currentFiles: FileList | null): Promise<any> => {
const formData = new FormData();
if (currentFiles) {
for (let i = 0; i < currentFiles.length; i++) {
formData.append("currentFiles", currentFiles[i]);
}
}
return http.post("/projects/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
};
formData를 사용했네요!! 이것으로 파일을 보낼수 있습니다.
formData는 무엇이든 들어가기 때문에
다른 것들도 보낼수 있는데 대충보면
const upload = (uploadProjects: IProjects, currentFiles: FileList | null): Promise<any> => {
const formData = new FormData();
formData.append("description", uploadProjects.description);
formData.append("frontName", uploadProjects.frontName);
formData.append("backendName", uploadProjects.backendName);
formData.append("dbmsName", uploadProjects.dbmsName);
formData.append("publishName", uploadProjects.publishName);
formData.append("webUrl", uploadProjects.webUrl);
if (currentFiles) {
for (let i = 0; i < currentFiles.length; i++) {
formData.append("currentFiles", currentFiles[i]);
}
}
return http.post("/projects/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
};
요런 식으로도 들어갈 수 있겠네요.
다음은 Springboot 편에서 계속 하겠습니다.
'React > React_TypeScript' 카테고리의 다른 글
TypeScript - nullish (1) | 2023.10.31 |
---|---|
React - TypeScript 인터페이스 (0) | 2023.10.20 |
React_TypeScript - 타입 추론 (0) | 2023.09.06 |
React_TypeScript - enum(열거형) , type (1) | 2023.09.06 |
React_TypeScript - readonly(읽기 전용) , tuple (튜플) (0) | 2023.09.06 |