펌위치 : http://blog.naver.com/legendx/40132716891
모바일 네트워크에서 서버로 보내는 자료는 일반적으로 문자열이지만 간혹 이미지를 전송해야 하는 경우가 있다.
Content-Type을 Multipart로 설정하면 byte 전송이 가능한데, 이 때 이미지를 서버로 전송할 수 있다.
Multipart를 구현한 지는 몇달 되었다. 그 때 당시 검색할 땐 Multipart로 이미지 전송하는 글들을 볼 수 있있지만, 문자열과 혼합된 여러 자료를 넘기는 방법은 소개되지 않았던 것으로 안다.
물론 시간이 지난 지금에서야 방법이 소개되었는지는 모르겠지만, 같은 고민을 하는 이들에게
작은 도움이 되고자 포스팅하려 한다.
Multipart는 말 그대로 여러 유형의 데이터를 전송할 때 사용되는 Content-Type 중 하나다.
본인도 본래는 서버로 문자열만 전송하다가 이미지를 전송하게 되어 사용하게 되었다.
자바에서는 HttpClient와 URLConnection이 있는데, 둘 다 잘 아는 것은 아니지만 우선 본인은
URLConnection을 사용하였다. HttpClient는 고려도 안해봤다. 그러나 byte로 전송을 해야 하기 때문에
URLConnection이 적절하다고 생각한다. HttpClient는 byte전송이 안되는 것으로 안다. 물론 본인이 틀렸을 수도 있다.
URL url = new URL("http://localhost/multipart.php");String boundary = "SpecificString";URLConnection con = url.openConnection();con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);con.setDoOutput(true);// 여기까지가 서버에 접속하기 위한 기본 설정이다.위 소스를 보자. url은 URL 객체로, 전송할 목적지 주소를 적어주면 된다.문자열로 boundary를 초기화하고 있는데, 이 때 사용되는 문자열은 어떠한 것이든 상관 없다.이 문자열은 넘겨지는 각 인자를 구분하기 위한 구분자이다.con은 URLConnection의 객체로, url에서 바로 열어줄 수 있다.Content-Type은 보는바와 같이 multipart/form-data로 정해주면 되고, boundary를 설정해주는데아까 정해놓은 문자열 boundary를 사용하면 되겠다.자주색으로 되어있는 곳만 자신의 실정에 맞게 수정하자.
위와 같이 했다면 전송할 준비는 마친 것이다. 아래부터 전송할 인자를 설정한다.
DataOutputStream wr = new DataOutputStream(con.getOutputStream());wr.writeBytes("\r\n--" + boundary + "\r\n");wr.writeBytes("Content-Disposition: form-data; name=\"no\"\r\n\r\n" + no);wr.writeBytes("\r\n--" + boundary + "\r\n");wr.writeBytes("Content-Disposition: form-data; name=\"table_name\"\r\n\r\n" +tableName);//여기까지가 문자열을 보내는 소스이다.위 소스에서 파란색은 서버단에서 받을 때 사용하는 Key다. PHP로 치자면$_POST["이 곳에 들어갈"]; Key 인 것이다.한 마디로, 넘어온 자료들을 식별하는 이름이라고 하자.자주색은 실제 넘길 값이다. 말 그대로 서버로 넘기고 싶은 자료(변수)를 넣어주면 된다.위에 보면 boundary 앞에 --을 붙였는데, --boundary 가 하나의 인자를 감싸는 형태로 추가된다. 하나의 인자 위 아래에 boundary가 있어서 boundary를 만나는 것으로 인자의 시작과 끝을 알 수 있는 것이다.만약 boundary를 "0090090"으로 정하였다면--0090090 이 문자열이 각 인자를 위 아래에서 감싸는 것이다.위 내용에서 \r\n은 줄바꿈 문자이다.위의 내용을 해석해보면(줄바꿈)--SpecificString(줄바꿈)Content-Disposition: form-data; name="no"(줄바꿈)(줄바꿈)16(줄바꿈)--SpecificString(줄바꿈)Content-Disposition: form-data; name="table_name"(줄바꿈)(줄바꿈)test...이하 줄임...이런식으로 될 것이다.
위에서 문자열을 넘기는 법에 대해 알아보았다. 이어서 아래의 소스를 사용하면 이미지도 같이 전송할 수 있다.
wr.writeBytes("\r\n--" + boundary + "\r\n");wr.writeBytes("Content-Disposition: form-data; name=\"image\"; filename=\"image.jpg\"\r\n");wr.writeBytes("Content-Type: application/octet-stream\r\n\r\n");FileInputStream fileInputStream = new FileInputStream(cropedImageUri.getPath());int bytesAvailable = fileInputStream.available();int maxBufferSize = 1024;int bufferSize = Math.min(bytesAvailable, maxBufferSize);byte[] buffer = new byte[bufferSize];int bytesRead = fileInputStream.read(buffer, 0, bufferSize);while (bytesRead > 0){// Upload file part(s)DataOutputStream dataWrite = new DataOutputStream(con.getOutputStream());dataWrite.write(buffer, 0, bufferSize);bytesAvailable = fileInputStream.available();bufferSize = Math.min(bytesAvailable, maxBufferSize);bytesRead = fileInputStream.read(buffer, 0, bufferSize);}fileInputStream.close();파란색 image는 역시 서버에서 사용할 변수명이고, 자주색 image.jpg는 서버 변수에 저장될 값이다.(여기선 파일명)자주색 cropedImageUri.getPath()는 전송할 파일의 경로이다. 전송하고픈 파일의 절대경로를 넣어주면 된다. file://로 시작한다.maxBufferSize는 1024로 냅두지만 문제가 생길 경우 임의로 수정한다.이미지를 전송하는 부분부터 아이폰의 그 것과 비교된다.본인이 잘못 알고 있는지는 모르겠지만, 아이폰보다 조금 복잡해보인다.이하 소스는 그대로 사용해도 무방하다.사실 소스는 이해하고 사용하는 것이 중요한데, 소스 전체를 설명드리지 못하는 점 양해 부탁드린다. 여러분의 검색능력을 본인은 믿는다.
여기까지가 문자와 이미지를 POST로 함께 넘기는 방법이다. 설정이 끝났으니 서버로 전송해보자. 사실 전송은 지금까지 계속 해왔다. wr.write- 메서드를 사용해서 말이다.
wr.writeBytes("\r\n--" + boundary + "--\r\n");wr.flush();단 두줄이지만 이 두 줄이 매우 중요하다. 우선 위의 boundary는 이 전의 boundary들과 다르다. 바로 뒤에 --이 붙는다는 것이다. boundary 뒤에 --이 붙음으로써 인자 나열이 끝났음을 알린다.보면 wr(DataOutputStream)의 writeBytes 메서드를 이용해서 인자를 넘겨주고 있다. 이런식으로 서버에 계속해서 자료를 전송한다.flush()를 호출함으로써 전송을 마무리한다.
마지막으로 전송이 잘 되었는지 서버에서 피드백하는 자료가 있다면, 그 자료를 받는 방법이다.
BufferedReader rd = null;rd = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));String line = null;while ((line = rd.readLine()) != null) {Log.i("Lifeclue", line);}생성했던 URLConnection 객체를 이용해 InputStream()을 가져올 수 있는데 이를 이용하여 서버에서 쏴주는 값을 받아올 수 있다. 서버에서 자료를 잘 받았을 때와 잘 받지 못했을 때를 구분해서 처리한다면 단말단에서는 전송한 자료가 잘 갔는지를 판단할 수 있다.
이렇게 POST방식으로 다른 자료형을 함께 보내는 법에 대해 알아보았다. 가끔은 졸려서, 가끔은 바빠서 포스트를 어려차례 나눠쓰는 바람에 내용이 부실할 지도 모르고 가끔은 오탈자나 문맥 이상등으로 이해할 수 없는 부분이 있을지 모르겠다. 여유시간에 작성하는 것인만큼 양해 부탁드린다.
작성자가 댓글을 삭제했습니다.
답글삭제