
* 겪고 있는 문제 상황을 최대한 자세하게 작성해주세요.
* 문제 해결을 위해 어떤 시도를 해보았는지 구체적으로 함께 알려주세요.
현재 부동산 매물입력 데이타 관련 웹프로그램을 만들고 있는중입니다.
챗gpt에도 물어봐도 제대로된 답변이 안되어서,
이렇게 질문을 남깁니다.
원하는 프로그램은
다중이미지 업로드의 배열에 관한 질문입니다.
현재 강의에 나와있듯 파이어베이스 스토리지를 사용중입니다.
문제는 이미지를 10개정도 첨부하여 sortable로 순서를 제 생각대로 고친후 업로드하면,
업로드되는 순서의 방식이 순차적이지 않고, 랜덤인듯 올라갑니다.
sortable를 사용해서 그런가하여, 사용하지 않고, 그대로 여러 이미지를 첨부하여 업로드해도
마찬가지로 랜덤으로 올라갑니다.
추후에
제 생각의 순서순으로 업로드된 이미지를
다시 그순서대로 load되는 페이지도 만들려고하다보니,
이미지의 순서가 중요한데, 잘안되어서 이렇게 질문을 남깁니다.
어떻게 하면 원하는 순서순의 업로드가 가능한지 해결책을 알려주시면 감사하겠습니다.
작성한 코드 및 에러 메세지
오류 발생 시, 작성한 코드 전체와 에러 메시지를 첨부해 주세요.
Tip 1) </> 아이콘을 눌러 코드박스를 만들어 보세요.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link href="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/style.min.css" rel="stylesheet" /> <link href="https://cdn.jsdelivr.net/npm/reset-css@5.0.2/reset.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> <link href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet" crossorigin="anonymous"> <link href="css/styles.css" rel="stylesheet" /> <script src="https://www.gstatic.com/firebasejs/10.4.0/firebase-app-compat.js"></script> <script src="https://www.gstatic.com/firebasejs/10.4.0/firebase-analytics-compat.js"></script> <script src="https://www.gstatic.com/firebasejs/10.4.0/firebase-auth-compat.js"></script> <script src="https://www.gstatic.com/firebasejs/10.4.0/firebase-firestore-compat.js"></script> <script src="https://www.gstatic.com/firebasejs/10.4.0/firebase-storage-compat.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> </head> <body> <div id="maemul_image_content_image1" class="d-flex maemulContent image image1"> <div class="col-sm-1 text-end px-3">매물사진</div> <div class="col-sm-11 " id="publicImg"> <input class="form-control" type="file" id="formFileMultiple1" multiple> <button class="btn btn-danger my-1" style="border-color: #ccc; white-space: nowrap;" onclick="deleteSelectedImage('publicPreview')">삭제</button> <button class="btn my-1" style="border-color: #ccc; white-space: nowrap;" onclick="handleChange()">업로드</button> <div id="publicPreview" class="my-1" style="max-width: 100%"> </div> </div> </div> <script> var uploadedImageUrls = []; // 업로드된 이미지 URL을 저장하는 배열 var filesArray = []; // 첨부된 파일 객체를 저장하는 배열 // 이미지 리사이징 함수 function resizeImage(file, maxWidth) { return new Promise((resolve) => { const reader = new FileReader(); reader.onload = function (event) { const img = new Image(); img.onload = function () { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // Calculate the new dimensions const width = img.width; const height = img.height; if (width > maxWidth) { const scaleFactor = maxWidth / width; canvas.width = maxWidth; canvas.height = height * scaleFactor; } else { canvas.width = width; canvas.height = height; } // Draw the image to the canvas ctx.drawImage(img, 0, 0, canvas.width, canvas.height); // Convert the canvas to a data URL with high quality canvas.toBlob(function (blob) { resolve(new File([blob], file.name, { type: file.type })); }, file.type, 1); // Set quality to 1 (maximum quality) }; img.src = event.target.result; }; reader.readAsDataURL(file); }); } // 이미지 첨부 미리보기 및 삭제 (매물사진) const inputElement1 = document.getElementById("formFileMultiple1"); inputElement1.addEventListener("change", handleFileSelect1); async function handleFileSelect1(event) { const files = event.target.files; if (!files || files.length === 0) { return; } const previewElement = document.getElementById("publicPreview"); for (let i = 0; i < files.length; i++) { const file = files[i]; if (!file.type.startsWith("image/")) { console.log("이미지 파일이 아닙니다."); continue; } const resizedFile = await resizeImage(file, 980); filesArray.push(resizedFile); // filesArray에 파일 객체 추가 const reader = new FileReader(); reader.onload = function (event) { const imgElement = document.createElement("img"); imgElement.src = event.target.result; imgElement.alt = resizedFile.name; // 이미지 요소의 alt 속성에 파일 이름 저장 imgElement.addEventListener("click", function () { this.classList.toggle("selected"); console.log("이미지 선택 상태 변경:", this.classList.contains("selected")); }); previewElement.appendChild(imgElement); }; reader.readAsDataURL(resizedFile); } // 파일 입력 필드를 리셋하고 남은 파일을 다시 추가 resetFileInput(); } // 삭제 버튼 함수 (매물사진) function deleteSelectedImage(previewId) { const previewElement = document.getElementById(previewId); const selectedImages = previewElement.querySelectorAll(".selected"); selectedImages.forEach(function (selectedImage) { const imageUrl = selectedImage.src; // 배열에서 이미지 URL 제거 uploadedImageUrls = uploadedImageUrls.filter(url => url !== imageUrl); // filesArray에서 해당 파일 객체 제거 filesArray = filesArray.filter(file => file.name !== selectedImage.alt); // 파일 이름을 기준으로 비교 // 콘솔에 삭제된 이미지 정보 출력 // console.log("삭제된 이미지 URL:", imageUrl); // DOM에서 이미지 요소 제거 previewElement.removeChild(selectedImage); }); // 파일 입력 필드를 리셋 resetFileInput(); } // 이미지 업로드 함수 (매물사진) function handleChange() { $("#publicPreview").empty().show(); uploadedImageUrls = []; // 배열 초기화 // filesArray는 이미 handleFileSelect1에서 초기화되므로 여기서는 초기화할 필요 없음 const fileInput = document.getElementById('formFileMultiple1'); if (fileInput.files) { Array.from(fileInput.files).forEach(file => { filesArray.push(file); createFile(file); }); } else { console.error("No files found in event target"); } } function createFile(file) { if (!file.type.match("image.*")) { alert("이미지 파일을 선택해주세요."); return; } else { var reader = new FileReader(); reader.onload = function (e) { saveToFirebaseStorage(e, file); }; reader.readAsDataURL(file); } } // 파일 입력 필드를 리셋하고 남은 파일을 다시 추가 (매물사진) function resetFileInput() { const fileInput = document.getElementById('formFileMultiple1'); const dataTransfer = new DataTransfer(); filesArray.forEach(file => dataTransfer.items.add(file)); fileInput.files = dataTransfer.files; } // 매물 사진을 Firebase Storage의 "images" 폴더에 저장하는 함수 (매물 사진) function saveToFirebaseStorage(evt, file) { var _key = new Date().getTime(); // 현재 시간을 기반으로 한 유니크한 키 생성 var storageRef = firebase.storage().ref(); // 폴더 경로 생성 var folderPath = "images/" + $("#dong_id").find(":selected").text() + "_" + $("#address").val() + "/"; var _fileName = _key.toString(); // 파일 이름을 _key로 설정 var uploadTask = storageRef.child(folderPath + _fileName).putString(evt.target.result, "data_url"); uploadTask.on( firebase.storage.TaskEvent.STATE_CHANGED, function (snapshot) { var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; console.log("Upload is " + progress + "% done"); }, function (error) { console.error("Error uploading image:", error); }, function () { uploadTask.snapshot.ref.getDownloadURL().then(function (downloadURL) { uploadedImageUrls.push(downloadURL); // 배열에 URL 추가 console.log("Firebase에 저장된 이미지 URL:", downloadURL); $("#publicPreview").append( `<img style="width:150px" src="${downloadURL}" onclick="removeImage('${downloadURL}')" />` ); }); } ); } //이미지 이동 $(function () { $("#publicPreview").sortable({ helper: 'original', }); }); </script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script> <script src="js/scripts.js"></script> <script src="https://cdn.jsdelivr.net/npm/simple-datatables@7.1.2/dist/umd/simple-datatables.min.js" crossorigin="anonymous"></script> <script src="js/datatables-simple-demo.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js" crossorigin="anonymous"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" crossorigin="anonymous"></script> </body> </html>
