반응형

React에서 Drag & Drop이 필요하여 아래와 같이 만들었습니다.

만들면서 HTML 구조와 React에서 사용 할 수 있게 작업 하였습니다.

 

자세한 사항은 아래 소스 중간중간에 주석을 남겨 두었으니 참고 바랍니다.

function uploadmodal({...props}) {    
    const [isTxtActive, setTxtActive] = useState(false);
    const [isWavActive, setWavActive] = useState(false);
    
    //Drag & Drop
    const handleDragStart = (type) => type == 'txt' ? setTxtActive(true) : setWavActive(true); //Drag를 시작 할 때 이벤트
    const handleDragEnd = (type) => type == 'txt' ? setTxtActive(false) : setWavActive(false); //Drag가 끝났을 때 이벤트
    const handleDragOver = (event,type) => { //파일을 드래그 하고 놨을 때 (이게 없으면 브라우저에서 실행 되거나 다운로드가 되는 증상이 나타남)
        event.preventDefault();
        event.stopPropagation();        
    };    

    const handelDropFile = (e,type) => { //파일을 놨을 때 이벤트
        e.preventDefault();
        e.stopPropagation();

        const newFiles = e.dataTransfer.files[0]; 
        console.log('[handelDropFile]newFiles :' ,newFiles);
    }    

	//label안에 css인 pointer-events:none를 하지 않으면 내용물 안에 영역으로 들어 갔을 때 DragEnter / DragLeave가 한번씩 타면서 초기화가 되는 증상이 나타남.

    return (
        <label 
            className={`${isTxtActive ? 'bg-[#efeef3] border-[#000]' : ''} w-[50vw] max-w-[1000px] min-w-[400px] flex flex-col items-center justify-center border-2 p-[20px] rounded-lg border-dotted mb-[10px] cursor-pointer`} 
            htmlFor="txt-file"
            onDragEnter={() => handleDragStart('txt')}
            onDragOver={handleDragOver}
            onDragLeave={() => handleDragEnd('txt')}                                        
            onDrop={(e) => handelDropFile(e,'txt')}
        >
            <div className="w-[50px] h-[50px] mb-[20px] pointer-events-none" >
                <img src={txtFileIcon} alt={txtFileIcon} />
            </div>
            <div className="mb-[10px] pointer-events-none" >                                    
                <span className="cursor-pointer text-[14px] bg-[#444] text-white px-[10px] py-[5px] rounded-full">파일 선택</span>                                            
            </div>
            <p className="pointer-events-none">또는</p>
            <p className="pointer-events-none">여기로 <span className="font-bold">텍스트(.txt) 파일</span>을 드래그 하세요.</p>                                        
            <input type="file" accept=".txt" id="txt-file" name="txtfile" style={{display:'none'}}></input>
        </label>   
    );
}

export default uploadmodal;
반응형

안녕하세요 오랜만에 적는 블로그 입니다.

 

프로젝트를 진행하면서 input 파일명에 실제 파일명만 적어두고 실제 파일은 없어도 될 경우가 있는거 같아서 한번 만들어보았습니다.

 

아래와 같이 적어주시면 input file type에 넣을 수 있습니다.

 

const myFile = new File(["file"], "파일실제 명", {type: "text", });
const dataTeansfer = new DataTransfer();
dataTeansfer.items.add(myFile);
document.querySelector('#ID').files = dataTeansfer.files;
alert(document.querySelector('#ID').files[0].name);

 

반응형

파일 다운로드 로직을 만들었을때 Return File을 사용하여 브라우저에서 다운로드를 받을 수 있게 만들었었다.

이번 프로젝트에서도 파일 다운로드 로직이 있었고 기존대로 사용하였는데 문제가 발생 하였다.

이미지로 데이터 화 시켜서 올렸을 때 '아이폰' 에서는 Content Type에 따라서 확장자가 변경되어 저장이 되고 있었다.

 

실제로 사용하던 Return 형태

return File(파일명, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 다운로드 받을 때 파일명);

 

Content Type을 보면 알겠지만 예전에 엑셀 파일을 다운로드 받을 때 사용했었던 Excel Content Type 이였는데

브라우저에서 받을 때 혹은 안드로이드에서 받을 때는 문제가 되지 않았다.

 

다만 아이폰에서 받았을 때 이미지 파일임에도 불구하고 뒤에 .xlsx가 붙어서 다운로드가 되었다.

이미지 형태로 여러가지 받아야 하는 상황이여서 파일이 유동적으로 변하기 때문에 골치 아팠다.

 

File 매개변수는 무조건 파일명과 Content Type을 입력해야했기 떄문에 자체적으로 판단하여 파일이 다운로드 됐으면 했는데 아래와 같은 방법으로 해결하였다.

return File(파일명, "application/octet-stream", 다운로드 시 파일명);

 

현재 파일 다운로드 로직 상 bmp , jpg , jpeg , jpe , jfif , tif , tiff , png 해당 확장자만 저장 되게끔 사용되고 있어서 

해당 확장자들은 정상적으로 다운로드 되는 것 까지 확인 하였다.

+ Recent posts