http://www.androidpub.com/1298998 게시물에 올렸던 것을 개수~_~?
이번에 App에서 적은 글과 파일을 선택해서 웹서버의 게시물을 올리는 기능을 하게되서 제작중인...;
POST로 파일 보내고 변수 전달하는 것을 해봤는데 일단 되긴 됩디다.
일 끝나는대로 업데이트 할 예정이고
뭔가 문제의 소지가 보이면 릿플 달아주시면 캼사하겠습니다.
일하다 뭔가 터지면 안되니 보이면 릿플좀 꼭 달아줘요 ㄱ-
거듭 이야기 하지만 귀차니즘에 쩔은 개발자이기 때문에
많은 것을 바라면 곤란...
일단 자바코드~~
package com.gsNetwork;
import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.Iterator; import java.util.List; import java.util.Map;
import org.apache.http.HttpResponse; import org.apache.http.HttpServerConnection;
import android.util.Log; import android.widget.EditText;
public class gsHttpConnect { static private HttpURLConnection m_con ; //private HttpResponse responer ; static private String m_cookies = "" ; static boolean m_session = false ; static long m_sessionLimitTime = 360000 ; /// 세션 시간제한 (밀리세컨드) 서버 설정시간이랑 맞추는게 좋을듯? static long m_sessionTime = 0 ; /// 세션을 얻은 시간 private String m_request ;
/// 주소, 메소드타입("GET" or "POST"), map(변수명, 값) 을 넣어주면 됨 public String request( URL url, String method, Map<String, Object> params ) throws IOException { /// 세션 시간이 넘어가지는 않았는지 확인한다. checkSession( ) ; /// 받아올 인풋스트림 /// POST방식일 경우 데이터를 전송할 아웃풋 스트림 OutputStream out = null ;
/// url에 연결 m_con = (HttpURLConnection)url.openConnection( ) ;
/// 메소드 타입을 지정 "GET"나 "POST"를 넣어야 하겠지~_~? m_con.setRequestMethod( method ) ; /// 인코딩 정의 HTTP방식으로 전송할때는 urlencoded방식으로 인코딩해서 전송해야한다. m_con.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" ) ;
/// 인풋스트림 쓸거라고 지정 m_con.setDoInput( true ) ; m_con.setInstanceFollowRedirects( false ) ; // 세션을 사용하려면 false로 설정해둬야함 /// 세션 생성해둔게 있으면 헤더에 셋팅해서 내가 전에 접속했던 녀석이라고 알려준다. if( m_session ) { m_con.setRequestProperty( "cookie", m_cookies ) ; }
/// 포스트방식일 경우 if( method.equals( "POST" ) ) { /// 데이터를 주소와 별개로 전송한다. m_con.setDoOutput( true ) ; /// 아웃풋 스트림 쓰기위에 아웃풋을 true로 켬 String paramstr = buildParameters( params ) ; /// 파라메터를 문자열로 치환 out = m_con.getOutputStream( ) ; /// 아웃풋 스트림 생성 out.write(paramstr.getBytes( "UTF-8" ) ) ; /// UTF-8포멧으로 변경해서 쓴다. out.flush( ) ; /// 플러쉬~ out.close( ) ; /// 스트림 닫기 Log.d( "-- gsLog ---", "post succes" ) ; /// 로그출력 } return getRequest( ) ; ////// } /// 어디선가 퍼온 소스들을 짜맞춰 만든 함수 /// 파일을 업로드하면서 변수 전달하고 리퀘스트 받는 함수입습죠 public String uploadAndRequest( URL url, Map<String, Object> params, Map<String, Object> files ) throws IOException { /// 세션 시간이 넘어가지는 않았는지 체크 checkSession( ) ; /// 파일 업로드시 사용할 인풋 스트림 FileInputStream mFileInputStream = null; /// 변수 조립할때 쓸 문자열들 final String lineEnd = "\r\n" ; final String twoHyphens = "--" ; final String boundary = "*****" ;
/// 연결하고 환경 셋팅 m_con = (HttpURLConnection)url.openConnection( ) ; m_con.setDoInput( true ) ; m_con.setDoOutput( true ) ; m_con.setUseCaches( false ) ; m_con.setRequestMethod( "POST" ) ; m_con.setInstanceFollowRedirects( false ) ; /// 세션 생성해둔게 있으면 헤더에 셋팅해서 내가 전에 접속했던 녀석이라고 알려준다. if( m_session ) { m_con.setRequestProperty( "cookie", m_cookies ) ; } m_con.setRequestProperty("Connection", "Keep-Alive"); m_con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
/////////////////////////////////////////////////////////////////////// /// 변수 전달 /////////////////////////////////////////////////////////////////////// DataOutputStream dos = new DataOutputStream( m_con.getOutputStream( ) ) ; /// 키와 값을 차례차례 빼낸다 for ( Iterator<String> i = params.keySet( ).iterator( ) ; i.hasNext( ) ; ) { String key = ( String )i.next( ) ;
/// 대충 생각해보면 감이 올지 않는가? /// --*****\r\n /// Content-Disposition: form-data; name=\"변수명1\"\r\n변수값1\r\n /// --*****\r\n /// Content-Disposition: form-data; name=\"변수명2\"\r\n변수값2\r\n /// --*****\r\n /// Content-Disposition: form-data; name=\"변수명3\"\r\n변수값3\r\n dos.writeBytes( twoHyphens + boundary + lineEnd ) ; //필드 구분자 시작 dos.writeBytes( "Content-Disposition: form-data; name=\"" + key + "\""+ lineEnd ) ; dos.writeBytes( lineEnd ) ; dos.writeBytes( String.valueOf( params.get( key ) ) ) ; dos.writeBytes( lineEnd ) ; } ////////////// /////////////////////////////////////////////////////////////////////// /// 파일 전달 /////////////////////////////////////////////////////////////////////// /// 키와 값을 차례차례 빼낸다 for ( Iterator<String> i = files.keySet( ).iterator( ) ; i.hasNext( ) ; ) { String key = ( String )i.next( ) ; String fileName = String.valueOf( files.get( key ) ) ; mFileInputStream = new FileInputStream( fileName );
/// 위에서 설명한 내용에서 변수값 대신 파일을 쓰는 것만 다르니까 더이상의 설명은 생략한다. dos.writeBytes( twoHyphens + boundary + lineEnd ) ; dos.writeBytes( "Content-Disposition: form-data; name=\"" + key + "\";filename=\"" + fileName + "\"" + lineEnd ) ; dos.writeBytes( lineEnd ) ; int bytesAvailable = mFileInputStream.available( ) ; int maxBufferSize = 1024 ; int bufferSize = Math.min( bytesAvailable, maxBufferSize ) ; byte[] buffer = new byte[bufferSize] ; int bytesRead = mFileInputStream.read( buffer, 0, bufferSize ) ;
/// 그림파일 읽어서 내용을 쏴준다. while( bytesRead > 0 ) { dos.write( buffer, 0, bufferSize ) ; bytesAvailable = mFileInputStream.available( ) ; bufferSize = Math.min( bytesAvailable, maxBufferSize ) ; bytesRead = mFileInputStream.read( buffer, 0, bufferSize ) ; } dos.writeBytes( lineEnd ) ; dos.writeBytes( twoHyphens + boundary + twoHyphens + lineEnd ) ; /// 변수 하나(파일하나) 전달 끗 mFileInputStream.close( ) ; dos.flush( ) ; } return getRequest( ) ; } public String getRequest( ) throws UnsupportedEncodingException, IOException { InputStream in = null ; /// 받아온 데이터를 쓰기위한 스트림 ByteArrayOutputStream bos = new ByteArrayOutputStream( ) ; /// 리퀘스트 데이터를 저장할 버퍼 byte[] buf = new byte[2048]; try { int k = 0 ; /// 읽은 라인수 long ti = System.currentTimeMillis( ) ; /// == 시간 체크용 == 서버에 따라 리퀘스트 오는 시간이 매우 오래걸림 in = m_con.getInputStream( ) ; /// 인풋스트림 생성 /// == 시간 체크용 == inputstream얻는 요기서 시간 10초이상 넘어가면 큰일남 /// 갤럭시 S에서 어떤앱은 WebView라던가 Http통신에서 15초인가 넘어가면 세션 끊기는 /// 원인을 알 수 없는 경우도 있었음 다른기기 다 잘되는데 오로지 갤럭시 S만!!! 그랬음 참고 바람요 Log.d( "---recTime---", "" + ( System.currentTimeMillis( ) - ti ) ) ;
/// 루프를 돌면서 리퀘스트로 받은내용을 저장한다. while( true ) { int readlen = in.read( buf ) ; if( readlen < 1 ) break ; k += readlen ; bos.write( buf, 0, readlen ) ; } /// 리퀘스트 받은 내용을 UTF-8로 변경해서 문자열로 저장 m_request = new String( bos.toByteArray( ), "UTF-8" ) ; /* File fl = new File( "/sdcard/rec.txt" ) ; FileOutputStream fos = new FileOutputStream( fl ) ; fos.write( bos.toByteArray( ) ) ; /**/ m_session = requestAndSetSession( ) ; return m_request ; } catch (IOException e) { /// 리퀘스트 받다가 에러가 나면 에러나면서 받은 메세지를 읽는다. if ( m_con.getResponseCode( ) == 500 ) { /// 버퍼 리셋하고 에러값 받을 인풋스트림 생성해서 레어메세지 얻기 bos.reset( ) ; InputStream err = m_con.getErrorStream( ) ; while( true ) { int readlen = err.read( buf ) ; if ( readlen < 1 ) break ; bos.write( buf, 0, readlen ) ; } /// 에러메세지를 문자열로 저장 String output = new String( bos.toByteArray( ), "UTF-8" ) ; /// 읽은 에러메세지를 출력한다. System.err.println( output ) ; } m_request = "error" ; throw e ; } finally /// 500에러도 아니면 그냥 접속 끊어버림.... -_- 안되는데 답있나? { if ( in != null ) in.close( ) ; if ( m_con != null ) m_con.disconnect( ) ; m_session = false ; m_cookies = "" ; m_request = "error" ;
} //return m_request ; } /// Request를 받되 세션 유지를 위해 쿠키를 저장한다. public boolean requestAndSetSession( ) { /// 맵에다 Http헤더를 받아냄 Map< String, List<String> > imap = m_con.getHeaderFields( ) ; /// 그리고 거길 뒤져서 쿠키를 찾아냄 if( imap.containsKey( "Set-Cookie" ) ) { /// 쿠키를 스트링으로 쫙 저장함 List<String> lString = imap.get( "Set-Cookie" ) ; for( int i = 0 ; i < lString.size() ; i++ ) { m_cookies += lString.get( i ) ; } // 2.3에서 정상작동하지 않습니다 .위의 코드로 대처합니다. //Collections c = (Collections)imap.get( "Set-Cookie" ) ; //m_cookies = c.toString( ) ; /// 세션을 저장했으니 return true ; } else { return false ; } }
public boolean checkSession( ) { if( !m_session ) { return false ; } if( System.currentTimeMillis( ) < m_sessionTime + m_sessionLimitTime ) { /// 제한시간 아직 안넘었음 세션 유지 연장시킴 m_sessionTime = System.currentTimeMillis( ) ; return true ; } else { /// 제한시간을 넘겼음 세션을 제거함 m_cookies = "" ; m_session = false ; return false ; } } /// 파라메터 값을 "변수명=변수값&" 형식의 텍스트로 변환해주는 함수 protected String buildParameters(Map<String, Object> params) throws IOException { StringBuilder sb = new StringBuilder( ) ; /// 파라메터가 없으면 그냥 쌩~ 한다 if( params == null ) { return "" ; } /// 키와 값을 차례차례 빼낸다 for ( Iterator<String> i = params.keySet( ).iterator( ) ; i.hasNext( ) ; ) { /// 함수 설명대로다 뭔말이 더 필요하냐. /// 변수명=변수값&변수명=변수값&변수명=변수값 이런 형태의 String를 만들기 위한 작업이다 String key = ( String )i.next( ) ; sb.append( key ) ; sb.append( "=" ) ; sb.append( URLEncoder.encode( String.valueOf( params.get( key ) ), "UTF-8" ) ) ; /// 값이 더 있으면 &를 넣어준다. if ( i.hasNext( ) ) { sb.append( "&" ) ; } } /// 만들어낸 문자열을 반환한다. return sb.toString( ) ; } }
그리고 업로드 처리하고 변수 출력는 PHP쪽 코드
<?php
$path = "./";
echo " // " ;
if ($_FILES["uploadFile1"]["error"] > 0) { echo "Error: " . $_FILES["uploadFile1"]["error"] . "<br />"; } else if( ($_FILES["uploadFile1"]["size"] / 1024) > 5120 ) { echo "too big size" ; } else {
echo "name - " . $_FILES["uploadFile1"]["name"] . "<br />"; echo "size - " . ($_FILES["uploadFile1"]["size"] / 1024) . "k<br />"; echo "type - " . $_FILES["uploadFile1"]["type"] . "<br />"; echo "tmpName " . $_FILES["uploadFile1"]["tmp_name"]; copy($_FILES["uploadFile1"]["tmp_name"], $path.$_FILES["uploadFile1"]["name"]);
}
echo " // " ;
if ($_FILES["uploadFile2"]["error"] > 0) { echo "Error: " . $_FILES["uploadFile2"]["error"] . "<br />"; } else if( ($_FILES["uploadFile2"]["size"] / 1024) > 5120 ) { echo "too big size" ; } else {
echo "name - " . $_FILES["uploadFile2"]["name"] . "<br />"; echo "size - " . ($_FILES["uploadFile2"]["size"] / 1024) . "k<br />"; echo "type - " . $_FILES["uploadFile2"]["type"] . "<br />"; echo "tmpName " . $_FILES["uploadFile2"]["tmp_name"]; copy($_FILES["uploadFile2"]["tmp_name"], $path.$_FILES["uploadFile2"]["name"]); }
echo " // " ;
echo $_POST["outText1"] ;
echo " // " ;
echo $_POST["outText2"] ;
echo " // " ; ?>
첨부파일에 프로젝트 파일과 php파일이 있습니다.
테스트 해보고싶으면
근사모 웹사이트에 가서 apm패키지 받아서 설치하고
pamina.java파일에 있는 ip주소만 자기 ip주소로 바꿔주고
php파일 넣어준다음 실행하면 끗
혹시 웹 호스팅해서 거기에 php파일 올려서 테스트 하는 사람들은 폴더에 권한 설정하는거 잊어먹고 안된다고 하면
스매시 한방 넣어드립니다.
문의 주소가 바뀌었습니다.
E-Mail : kottodat@naver.com
Homepage : kottodat.com ->> raidparty.net
(아직 앞 주소도 죽은건 아니지만 raidparty.net에 질문해주시면 감사하겠습니다.)
과제로 보이는 질문은 쌩~ 합니다.
차려진 밥상에 떠먹여주기까지 해달라는 메일도 휴지통으로 흘려보냅니다.
킈킈
좋은 정보 감사합니다. 저는 이런식으로 했었네요.
http://theeye.pe.kr/entry/how-to-get-and-multipart-post-on-android-platform
잘보고갑니다.