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에 질문해주시면 감사하겠습니다.)

 

 

과제로 보이는 질문은 쌩~ 합니다.

 

차려진 밥상에 떠먹여주기까지 해달라는 메일도 휴지통으로 흘려보냅니다.

 

 

 

 

profile

킈킈