인터넷 찾아가며 이것저것 짜집기도 하고 영 별거 아닌걸로 고생아닌고생하니까 짜증이 나네요...


그래서 제가 짠거 공개할게요.

springdml restTemplate 이용해서 했고요..

인터넷 찾아보니, 이게 뭐 convert가 좀 문제라서...

한글이 마구 깨지는데..

이거 구글링 열심히해서 어떤분 소스 베껴다가 넣었어요.

원본 주소 : https://gist.github.com/ucpwang/949145408a12bb40a671


주석같은거 안달려 있으니 알아서 보시면 될거 같고요.

contents에서 img태그 찾아서 #n 으로 치환해서 멀티파트로 파일 넘기는것까지 구현했습니다.

error코드 인증실패 리턴시에는 토큰값 갱신 하시는 로직 따로 작성하시면 되어요.



public String blogPost(String token, String title, String contents) { contents = contents.replaceAll("<br>", ""); contents = contents.replaceAll("<BR>", ""); List<String> imageSrcs = new ArrayList<>(); List<Resource> resources = new ArrayList<>(); int startIdx = 0; int imgIdx = contents.indexOf("<img", startIdx); while(imgIdx > -1){ int srcIdx = contents.indexOf("//image", imgIdx); int endIdx = contents.indexOf("\"", srcIdx); String imgSrc = contents.substring(srcIdx, endIdx); imageSrcs.add(imgSrc); startIdx = endIdx; imgIdx = contents.indexOf("<img", startIdx); } int idx = 0; for(String imageSrc : imageSrcs){ contents = contents.replace(imageSrc, "#"+idx); idx++; int qIdx = imageSrc.indexOf("?"); if(qIdx < 0){ qIdx = imageSrc.length(); } imageSrc = imageSrc.substring(0, qIdx); String fileSrc = imageSrc.replace(imageServerHost, saveDirectory); Resource file = new FileSystemResource(fileSrc); resources.add(file); } String header = "Bearer " + token; // Bearer 다음에 공백 추가 RestTemplate restTemplate = new RestTemplate(); String apiURL = "https://openapi.naver.com/blog/writePost.json"; try { for (HttpMessageConverter<?> hmc : restTemplate.getMessageConverters()) { if (hmc instanceof AllEncompassingFormHttpMessageConverter) { /** AllEncompassingFormHttpMessageConverter 생성자 내용 일부 가져와서 수정 **/ List<HttpMessageConverter<?>> partConverterList = new ArrayList<HttpMessageConverter<?>>(); partConverterList.add(new ByteArrayHttpMessageConverter()); StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8")); stringHttpMessageConverter.setWriteAcceptCharset(false); partConverterList.add(stringHttpMessageConverter); partConverterList.add(new ResourceHttpMessageConverter()); partConverterList.add(new SourceHttpMessageConverter()); if (ClassUtils.isPresent("javax.xml.bind.Binder", AllEncompassingFormHttpMessageConverter.class.getClassLoader())) { partConverterList.add(new Jaxb2RootElementHttpMessageConverter()); } if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", AllEncompassingFormHttpMessageConverter.class.getClassLoader()) && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", AllEncompassingFormHttpMessageConverter.class.getClassLoader())) { partConverterList.add(new MappingJackson2HttpMessageConverter()); } else if (ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", AllEncompassingFormHttpMessageConverter.class.getClassLoader()) && ClassUtils.isPresent("org.codehaus.jackson.JsonGenerator", AllEncompassingFormHttpMessageConverter.class.getClassLoader())) { partConverterList.add(new MappingJackson2HttpMessageConverter()); } ((AllEncompassingFormHttpMessageConverter) hmc).setPartConverters(partConverterList); } } HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", header); MultiValueMap<String, Object> parameters = new LinkedMultiValueMap<String, Object>(); parameters.add("title", title); parameters.add("contents", contents); for(Resource resource : resources){ parameters.add("image", resource); } HttpEntity<?> httpEntity = new HttpEntity<>(parameters,headers); ResponseEntity<HashMap> re = restTemplate.exchange(apiURL, HttpMethod.POST, httpEntity, HashMap.class); System.out.println(re); return (String) re.getBody().get("error_code"); } catch (Exception e) { System.out.println(e); } return null; }


오래전 개인적으로 프로젝트를 수주받아 일을 하던차.

이미지 업로드를 해야하는데, drag & drop 기능을 넣어 달란다.


"아니 그게 active-x 없이 되는 거야?"


"몰라. 너가 알아서해"


이러던 와중 찾아보니 html5에서 drag&drop이 되더라.

그래서 이걸 input file element를 이용해 동기화해서 이용하려고 해보니.


input file은 보안 문제상 javascript에서 set value가 불가능하다고. ㅠ


하긴 생각해보면 아무파일이나 local에서 읽어다가 막 올릴 수 있겠지.

인증서도 막 올릴수 있겠지. ㅠ


근데 이런 문제는 css로 해결할 수 있다니.

얼마전부터 css를 하다보니 참 새삼 위대함을 느낀다.



일단 JQGRID를 이용해서 해당 그리드에 드랍을 하면,  

파일 정보를 읽어서 그리드에 표시하고 저장버튼을 눌러 저장을 할 수 있는 형식으로 만들었다.

물론 여기까지 오는데 꾀 많은 템플릿? 데모? 를 만들었다.




그리드 부분을 아래처럼 div로 감싸고 droparea란 id로 지정을 했다.

 

 <div style="float: left;" id="droparea">

    <table id="theGrid01"></table>
    <table id="thePager01"></table>
</div>

그리고 드래그 엔터시와 아웃시 살짜쿵 스타일 변화를 주었다.

  $('#droparea').on('dragenter', function (e) 

{

    e.stopPropagation();

    e.preventDefault();

    $(this).css('border', '2px dotted #0B85A1');

});

$('#droparea').on('dragleave', function (e) 

{

     e.stopPropagation();

     e.preventDefault();

     $(this).css('border', '');

});

 


그리고 실제 파일 드랍시 발생하는 부분이다.

     $('#droparea').on('drop', function (e){

         $(this).css('border', '');

         e.preventDefault();

         var files = e.originalEvent.dataTransfer.files;

     

         handleFileUpload(files);

    });

위에서 보다시피 이벤트에서 파일을 얻어와 그걸 handleFileUpload에 넘긴다.


자 그럼 그 내용이 뭔지 보자.

// 소스 내용 자체는 참 쉽다.

var fd = new FormData();

// 일단 FormData를 local변수로 하나 생성하고

function handleFileUpload(files,obj)

{

    fd = new FormData(); // FormData를 초기화 하는 이유는 드랍시마다 초기화 하려고..

    // 그리드도 초기화

    $("#theGrid01").jqGrid("clearGridData", true).trigger("reloadGrid");


    // 드랍된 파일이 몇개일까..

    for (var i = 0; i < files.length; i++) 

    {        

        // fd에 파일을 추가한다.

        fd.append('file_'+i, files[i]); 

 

        var grid = $("#theGrid01");

        var rowId = grid.jqGrid('getGridParam', 'reccount');

        rowId++;

        rowId = rowId + "";

        // 파일 사이즈를 구해서

        var sizeStr="";

        var sizeKB = files[i].size/1024;

        if(parseInt(sizeKB) > 1024)

        {

            var sizeMB = sizeKB/1024;

            sizeStr = sizeMB.toFixed(2)+" MB";

        }

        else

        {

            sizeStr = sizeKB.toFixed(2)+" KB";

        }

        

        var parameters = {

            rowID : rowId,

        // 초기 데이터를 넣고

            initdata : {"FILE_NAME":files[i].name,"FILE_SIZE":sizeStr},

            position : "last",

            useDefValues : false,

            useFormatter : false,

            addRowParams : {

                extraparam : {},

                keys : true

            }

        }

        // 그리드에 row를 추가

        grid.jqGrid('addRow', parameters);

        grid.jqGrid('setCell', rowId, "ST", gv_insert, "");

        grid.jqGrid('setCell', rowId, "AT", "I");

 

    }

}


위 처럼 하면 전송할 폼데이터 및 그리드에 해당 파일 정보가 쓰인다.


마지막으로 저장 버튼 누를시 이벤트는

function txcall(txid) {

    

    

    var url = "";

    var mydata = "";

    switch (txid) {

    case "SAVE":

        url = "호출경로";

        mydata = fd; // 아까 위에서 생성한 폼데이터

        break;

    }

    transactionFile(txid, url, mydata, "txcallback");

}

transactionFIle은 jquery의 ajax를 이용해서 만든 함수다.

결국 그냥 ajax로 post방식으로 서버로 전송하는거다.

 

위 내용은 php로 했고, 서버사이드프로그램은 뭘 해도 상관없을듯 하다?...


추가적으로 끄적이자면. 큰 용량의 파일을 업로드시. 서버에 저장공간이 남아돈다면 모를까.

적당한 이미지로 보여주는것이 좋다.

PHP에서는...


thumb.php라는 오픈소스가 있는데, 이것을 이용해서 이미지를 사이즈를 작게 만들어서 저장하는 것도 방법이라면 방법이다.



드래그앤 드랍 참조 1 : http://hayageek.com/drag-and-drop-file-upload-jquery/


 

자바스크립트 배열에 대해 알아보자.
1. 배열은 어떻게 선언할까..


  var arr_temp = new Array(); // 저는 이걸 가장 많이 씁니다.
  var arr_temp = []
  
  또는 선언과 동시에 값을 넣을 수 있다.
  var arr_temp = [11,22,33,44];
  그리고 배열안에 배열도 가능하다
  var arr_temp = [[1,2,3],[4,5,6],[7,8,9]];
  또 위는 아래와 같다.
  var arr_temp = [];
  arr_temp[0] = [1,2,3];
  arr_temp[1] = [4,5,6];
  arr_temp[2] = [7,8,9];
  뭐 이렇게 다양한 방법으로 배열 선언이 가능하다.

2. OBJECT는 어떻게 선언할까..


  var obj_temp = {}; // 저는 이걸 가장 많이 씁니다.
  var obj_temp = new Object();

  이것도 마찬가지로 선언과 동시에 값을 넣을 수 있다.
  var obj_temp = {key1:"aa", key2:"bb"};

  그리고 오브젝트 안에 오브젝트도 가능하다.
  var obj_temp = {key1:{num1:"aa", num2:"bb"}};

  

3. 자 그럼 지원되는 함수는 뭐가 있을까요?..  

(참고 : http://www.w3schools.com/jsref/jsref_obj_array.asp)


  뭔가 영어로 엄청 써있다. 근데 자주 쓰일만한것을 알아보자
  
  push() : 배열의 마지막에 원소를 추가.
  ex) arr_temp.push(temp);

  unshift() : 배열의 첫번째에 원소를 추가.
  ex) arr_temp.unshift(temp);

  shift() : 배열의 첫번째 원소를 삭제. 스텍을 연상하면 될 것이다.
  ex) arr_temp.shift();
  

  pop() : 배열의 마지막 원소를 삭제.

  ex) arr_temp.pop();
 
  slice() : 배열을 index로 substring처럼 쪼갠다고 보면 된다.

  ex) arr_temp.slice(2, 3);
  
  concat() : 배열 두개를 합친다.
  ex) arr_temp1.concat(arr_temp2);

  보통 이것 외에 다른것 써본적이 없다. 딱히 쓸일이 없다랄까..

  이제 OBJECT에는 어떤 함수가 있나 보자.

  여기도 마찬가지로 영어로 뭔가 많다.
  
  keys() : 말 그대로 key를 배열로 반환해준다. key로 ordering을 한다.
  ex) Object.keys(obj_temp);
  
  values() : 이건 value를 배열로 반환해준다. key로 ordering을 한다.
  ex) Object.values(obj_temp);

  keys()와 values()는 함꼐 쓰면 용이 할 수 있겠다.
  
  entries() : key와 value를 2차원 배열로 만들어 준다. 마찬가지로  key로 ordering을 한다.
  ex) Object.entries(obj_temp);

자, 이 외에것은 위의 링크에 들어가면 매우 잘 나와 있다.
참고해보시길.



+ Recent posts