때때롱 프로그램을 맹글때 이미지(사람이름아님)들이 필요할 때가 있당.
이때 1개, 2개 필요하면 그냥 검색해서 마우스 오른쪽 버튼을 이용하여, 다른이름으로 저장하거나
이미지주소를 복사하면 되지만, 혹여 꽤 마니 필요하다면 꽤나 귀찮은 단순 반복 작업에, 파일명까지
수정해야 한다면, 삼겹살집에서 불이 약해빠져, 삼겹살이 익기 전에 식욕감퇴와, 기다림을 달랜 술이
당신을 고주망태로 맹글어 버리는 일이 비일비재한 것과 일맥상통하게 된당.
(생각만 해도 맛난 삼겹살을 혀로 녹이지 못한 느낌에 소름이 장맛비처럼 온몸에 홍수친당)
따악 봐동 OS위에서 데스크탑 어플로 맹글면 유용한 유틸리티가 될 것이지만(모찌롱 이쓸거당),
여기선 AJAX 파일 다운로드도 화긴할 겸,겸사 겸사 브라우져에서 자스로 맹글어보장.
내 일사천리 게으른 뇌는 구글의 이미지 검색결과를 AJAX로 가져와썽, 결과 내용 쭝의
이미지 URL을 긁고 글거성, 다시 이미지URL 자체를 AJAX로 요청!, 이미지파일을
BLOB(Binary Large Object 블롭)로 받으면 내맘대로 파일명을 주어서 download가
가능하지 안켔썽!이라 잘동 재잘 재잘 거린당.
문제가 있당. 웹 개발자라면 AJAX에 외부URL을 걸때 console에 보이는 아래 에러가 이해되야 한당.
Access to XMLHttpRequest at 외부URL from origin 로컬URL has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Cross-Origin의 Same-Origin정책 문제로 인해 서버와 서버사이드 프로그램이 필요한 귀차니즘을
먼저 브라우져 플러그인으로 해결하장. chrome 웹 스토어 에 가서 cross origin으로 껌쌕하면
플러그인이 여러개 나오는뎅, 아래꺼시 사람들이 마니 설치한 거시니, 업스면 그냥 크롬에 추가하장!
추가했다면 AJAX 확인시 자주 쓰일 친구니, 아래 압정핀을 클릭 브라우져 탭에 고정하장.
확장프로그램에 추가만 하면 되진 않고, 아래 처럼 ON을 시켜줘야 한당.
못된 범죄 아그들에게 악용될 수 있으닝, 쓰지 않을 때는 OFF시키는 습관을 갖장.
준비가 되었당. 눈과 손 Ready?, 항상 시작은 기본 핵심만 먼저 화긴토록 하장!
아래 소스를 카.복해서 실행하여 보장,개발자라면 항상 F12를 눌러 로그를 꼬옥 보는 습관!!!
ajaxImgDownBasic.html
<!DOCTYPE html>
<meta charset="UTF-8">
<script>
//괘니 즉각실행함수 한번 써봄
(function fileDownload(){
//샘플용 그냥 짧은 이미지 URL
let pImgURL="https://dimg.donga.com/wps/NEWS/IMAGE/2021/02/10/105377249.2.jpg";
let xhr = new XMLHttpRequest();
xhr.responseType="blob"; // 눈여겨 봐주삼
xhr.open("get",pImgURL,true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
// 아래 중요 누느로 화긴 BLOB(Binary Large OBject)
console.log("체킁:",xhr.response);
// a 태그 객체 생성후 download속성 부여 그리고 클릭!
let aTag = document.createElement("a");
// URL.createObjectURL은 blob을 URL로 인식하게 해줌
aTag.href= URL.createObjectURL(xhr.response);
aTag.download = `나의로제님.jpg`;
aTag.click(); // 강제 클릭
//aTag는 document에 붙여주지 않았으닝, 메모리에만 있다가 사라짐
}else { // 일부러 else문 넣었음, 200아닐땡 코드 보려공
console.log("서버에서 거부코드:",xhr.status);
}
}
}
xhr.send();
})();
</script>
즉각실행함수를 사용해쓰닝 바로 실행되어 파일이 나의로제님.jpg란 이름으로 당근 다운로드 되공,
console에는 아래그림처럼 로그가 찍히는 거시 누네띠게 누네 보일거시당.(첨 본다면 유레카!당)
AJAX사용 파일 다운로드 추가 뽀인또는 xhr.responseType="blob" 이고,파일 자체를
a 태그에 심는 뽀인또는 URL.createObjectURL의 사용이당.(낯설다면 그저 친해지면 그만이당)
요 타이밍에 지금도 공부를 아주 욜씨미 하고 이쓸 성실한 그들의 아래와 같은 질문이 예상 될 수 있당.
구찌 blob로 받지 않공, a 태그의 href에 이미지URL을 넣공, 바로 download속성을 추가해서
아래 처럼 맹글공, 클릭이벤트를 발생시키면 더 편하지 않을까용?
<a href="https://dimg.donga.com/wps/NEWS/IMAGE/2021/02/10/105377249.2.jpg"
download="나의로제님.jpg">다운로드</a>
좋은 생각! 멋지당!, BUT, a 태그의 download속성은 Cross Origin정책의 제한으로
로컬(내서버)URL인 경우에 다운로드가 되공, 외부 URL인 경우 브라우져가 열라 연당!!
위의 경우 직접해보면 다운로드 안되공, 브라우져가 이미지를 열어주는 거시 확인된당!
다운로드는 구현했지만, 원하는 걸 맹글려면 한가지가 더 필요하당. 이미지 URL!
이미지URL을 가져오는 건 구글의 이미지 검색결과를 가져다 쓰면 좋지 않겠는강!
구글에서 이미지 검색할 땡 필수옵션은 아래와 같당(검색어에 필요한 걸 써주면 된당)
https://www.google.com/search?q=검색어&tbm=isch
핵심 필요한 건 모두 화긴했으니, 이제 맹글기로 했던 이미지 검색 다운로더를 맹글장
이제까지 한 거슬 모두 모으공, 추가로 CSS 쪼메 추가하면 아래와 같은 거슬 누구낭? 맹글수 있당.
imgSchDown.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#wrapper {
margin:10px auto;
width:60%;
border:1px solid black;
text-align: center;
}
#disp {
max-height:70vh;
border:1px solid black;
text-align: center;
overflow:auto;
resize: both;
}
#disp::-webkit-scrollbar {
/*display: none; */
width: 3px;
}
h1{
background-color: orange;
}
</style>
</head>
<body>
<div id="wrapper">
<h1>© E7E 메롱</h1>
<input type="text" id="schWord" value="" placeholder="검색할 이미지 적어주삼" autofocus>
<input type="button" id="schBtn" value="검색"><br><br>
<div id="disp"></div>
</div>
<script>
//필요한 전역변수 선언
const myDisp = document.querySelector("#disp");
const mySchWord = document.querySelector("#schWord");
const mySchBtn = document.querySelector("#schBtn");
const preSchURL = "https://www.google.com/search?q=";
const postSchURL = "&tbm=isch"; // 이미지 서치
//검색버튼 이벤트, 엔터키 이벤트
mySchBtn.onclick = fSch;
mySchWord.onkeydown = function(){
if(event.keyCode == 13){
fSch();
}
}
//이미지 URL검색함숭
function fSch(){
let schURL = `${preSchURL}${mySchWord.value}${postSchURL}`;
let xhr = new XMLHttpRequest();
xhr.open("get",schURL,true);
xhr.onreadystatechange = ()=>{
if(xhr.readyState == 4 && xhr.status == 200){
let cont = xhr.responseText;
// sIndex는 찾기시작 index값으로 대략 튜닝값(찾을 문자열이 실제 더 뒤에 나옴,내맘!)
let sIndex = 50000;
let fIndex =1;
myDisp.innerHTML="";
while( (startIndex = cont.indexOf("[\"https://",sIndex)) != -1){
console.log("최초",startIndex);
sIndex = startIndex+2;
console.log("시작",sIndex);
let eIndex = cont.indexOf("\"",sIndex);
console.log("끄읕",eIndex);
let imgURL = cont.substring(sIndex,eIndex);
console.log("이미지URL",imgURL)
if(imgURL.includes(".jpg")){
console.log(imgURL);
fileDownload(imgURL,fIndex);
fIndex++;
}
}
}
}
xhr.send();
}
//개별 이미지URL을 blob로 받아서 다우로드해주는 함숭
function fileDownload(pImgURL,pIndex){
let xhr = new XMLHttpRequest();
xhr.responseType="blob";
xhr.open("get",pImgURL,true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
console.log("체킁:",xhr.response); // BLOB(Binary Large OBject)
myDisp.innerHTML += `<h4>${mySchWord.value}${pIndex}.jpg 다운로딩</h4>`;
let aTag = document.createElement("a");
aTag.href= URL.createObjectURL(xhr.response);
aTag.download = `${mySchWord.value}${pIndex}.jpg`;
aTag.click(); // 강제 클릭
//aTag는 document에 붙여주지 않으므로, 메모리에만 있다가 사라짐
setTimeout(()=>{
myDisp.scrollTo(0,myDisp.scrollHeight);
},100)
}else {
console.log("서버에서 거부코드:",xhr.status);
}
}
}
xhr.send();
}
</script>
</body>
</html>
추가적으로 주석과 log출력을 다라다라 달아놓았으닝, 누네 쪼메만 힘주고,
현재를 과거로 맹그는 시간투자만 더덕더덕 한다면 코드 이해는 그리 어렵지 않당.
구찌 어거지로 한가지 더 이야기 한다면, 이미지URL을 글거오는 AJAX안에서 개별이미지URL을
이용 다시 AJAX로 Blob로 받아오는, 비동기속에 비동기 사용한 부분에 주목했으면 한당.
실제 실행해 보면,파일이 순서대로 오는 거시 아님을 누네띠게 화긴할 수 있당.(당신은 누니좋당!)
비동기를 동기로 바꾸면 [xhr.open의 마지막 매개변수를 false롱] 순서대로 오는뎅 아주 느리당당!.
나의 경우, 아래 캡쳐처럼 로제님 이미지를 음청 쉬웁게 받아챙겼당! (다운로드폴더에 있더랑!)
참고로 구글이미지 검색은 100X100 사이즈의 아이콘 파일도 검색결과 상위에 포함해 주는뎅,
(검색결과의 HTML 소스를 뒤척뒤척하면 _setImgSrc 부분을 찾고 싶지 않아도 잘 보인당!
만약 이거슬 다운받고 싶다면,아래 뽀인또 코드를 참고해서 맹글어보랑. (난 별로 무관심이당!)
xhr.onreadystatechange = ()=>{
if(xhr.readyState == 4 && xhr.status == 200){
let cont = xhr.responseText;
let sIndex = 20000;
let startIndex = cont.indexOf("_setImgSrc(",sIndex);
console.log("최초",startIndex);
sIndex = startIndex+18;
console.log("시작",sIndex);
let eIndex = cont.indexOf("')",sIndex);
console.log("끄읕",eIndex);
//console.log("체킁:",cont.substring(sIndex,eIndex).replaceAll("\\",""));
testBD.src = cont.substring(sIndex,eIndex).replaceAll("\\","");
}
}
꼬치 꼬치 닥꼬치 이유를 캐는 취조
잘근 잘근 으드득 믹스 감정 공명 호통
엇나간 두근반 세근반 기대로 기다렸당.
왜 그랬냐공?, 왜엥? 서슬퍼런 질문을...
암시적 통통보 메세지!, 던지깅~
읽씹, 안읽씹 외면 고립!, 스텔스 펼치기~
술래를 버리는 차단!, 카운터 펀치~
잘 짠 3단 콤보는 숨바꼭질을 미제로 남겼당.
잊고 있었당. 열라 문 두드리는 소리!
문 밖에 악귀가 일찍 와 있었나 보당.
악기 소리라도 들려줄깡? 벌써 갔넹!
아마도 그건 알 수 없는 악기 소리였나 보당
https://www.youtube.com/watch?v=p1asWglxMZs
흘렁 흘렁 슬라이더 전자알밤 (0) | 2023.07.20 |
---|---|
대충 이미지 검색 왕창 다운로띵 ajax 2 (0) | 2023.07.17 |
알칼리아닌 산성비로 잠재능력 깨워용~~ (0) | 2023.07.12 |
근시안과 노안엔 돋보기를 ... (1) | 2023.07.10 |
사랑(Heart)은 오락가락(Swing) (2) | 2023.07.06 |