2014-10-14 2 views
1

죄송합니다. 다시 가져 오십시오. 처음 안드로이드 앱을 개발하기 시작했을 때 HttpClient를 사용하고있었습니다. Google이 공식적으로이 클래스를 Android의 최신 버전 대신 사용하지 않기로 결정했음을 알았습니다. 그들은 개발자가 대신 HttpUrlConnection을 사용하도록 권장합니다.HttpUrlConnection 및 파일 문제

GAE에서 호스팅되는 PHP 서버 API에 파일 (JPEG)을 업로드하려고하면 최근에 벽에 직면했습니다. 이를 달성하기 위해 Multipart를 사용하는데 많은 노력을 기울였습니다. 나는 다음과 같은 클래스를 사용하여 끝났다. 그러나 그것은 아직 알려지지 않은 일부 이유로는 효과가 없습니다. PHP 서버 API가 성공적으로 POST 데이터를 수신하지만 파일을받을 수 없습니다. 내 코드가 잘못된거야?

궁금한 점이 있으시면 isset($_FILES["profile_picture"])을 사용하여 서버와 관련이 없는지 확인할 수 있습니다. 여기

내 클래스 :

package net.XXXXX; 

import android.util.Log; 

import java.io.BufferedInputStream; 
import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.net.URLConnection; 
import java.util.ArrayList; 
import java.util.List; 

import javax.net.ssl.HttpsURLConnection; 


public class MultipartUtility { 

    private HttpURLConnection mConnection; 
    private OutputStream outputStream; 
    private PrintWriter mWriter; 
    private final String boundary; 

    private static final String LINE_FEED = "\r\n"; 
    private final static String CHARSET = "UTF-8"; 
    private final static String API_URL = "https://select-connection.appspot.com/"; 
    public static final String LOG_TAG = "APIRequestHandler"; 
    public static final int CONNECT_TIMEOUT = 15000; 
    public static final int READ_TIMEOUT = 10000; 

    /** 
    * ... 
    */ 
    public MultipartUtility() throws IOException { 

     // creates a unique boundary based on time stamp. 
     boundary = "===" + System.currentTimeMillis() + "==="; 

     URL url = new URL(API_URL); 
     mConnection = (HttpsURLConnection)url.openConnection(); 
     mConnection.setConnectTimeout(CONNECT_TIMEOUT); 
     mConnection.setReadTimeout(READ_TIMEOUT); 
     mConnection.setRequestMethod("POST"); 
     mConnection.setRequestProperty("Accept-Charset", "UTF-8"); 
     mConnection.setRequestProperty("Accept", "application/json"); 
     mConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); 
     mConnection.setUseCaches (false); 
     mConnection.setDoInput(true); 
     mConnection.setDoOutput(true); 

     outputStream = mConnection.getOutputStream(); 
     mWriter = new PrintWriter(new OutputStreamWriter(outputStream, CHARSET), true); 
    } 

    /** 
    * ... 
    */ 
    public void addFormField(String name, String value) { 
     mWriter.append("--" + boundary).append(LINE_FEED) 
       .append("Content-Disposition: form-data; name=\"" + name + "\"") 
       .append(LINE_FEED) 
       .append("Content-Type: text/plain; charset=" + CHARSET) 
       .append(LINE_FEED) 
       .append(LINE_FEED) 
       .append(value) 
       .append(LINE_FEED); 
     mWriter.flush(); 
    } 

    /** 
    * ... 
    */ 
    public void addFilePart(String fieldName, File uploadFile) 
      throws IOException { 
     String fileName = uploadFile.getName(); 
     mWriter.append("--" + boundary).append(LINE_FEED) 
       .append("Content-Disposition: form-data; name=\"" + fieldName + "\"; filename=\"" + fileName + "\"") 
       .append(LINE_FEED) 
       .append("Content-Type: " + URLConnection.guessContentTypeFromName(fileName)) 
       .append(LINE_FEED) 
       .append("Content-Transfer-Encoding: binary") 
       .append(LINE_FEED) 
       .append(LINE_FEED); 
     mWriter.flush(); 

     FileInputStream inputStream = new FileInputStream(uploadFile); 
     byte[] buffer = new byte[4096]; 
     int bytesRead; 
     while ((bytesRead = inputStream.read(buffer)) != -1) { 
      outputStream.write(buffer, 0, bytesRead); 
     } 
     outputStream.flush(); 
     inputStream.close(); 

     mWriter.append(LINE_FEED); 
     mWriter.flush(); 
    } 

    /** 
    * ... 
    */ 
    public void addHeaderField(String name, String value) { 
     mWriter.append(name + ": " + value).append(LINE_FEED); 
     mWriter.flush(); 
    } 

    /** 
    * ... 
    */ 
    public String finish() throws IOException { 
     String response; 

     mWriter.append(LINE_FEED).flush(); 
     mWriter.append("--" + boundary + "--").append(LINE_FEED); 
     mWriter.close(); 

     // checks server's status code first 
     int status = mConnection.getResponseCode(); 
     if (status == HttpURLConnection.HTTP_OK) { 

      response = ApiRequestHandler.convertStreamToString(new BufferedInputStream(mConnection.getInputStream())); 

      mConnection.disconnect(); 
     } else { 
      throw new IOException("Server returned non-OK status: " + status); 
     } 

     return response; 
    } 
} 

그리고 이것은 내가 그것을 사용하는 방법입니다 :

try { 
       MultipartUtility connection = new MultipartUtility(); 
       connection.addFormField("action", "update_picture"); 
       connection.addFormField("user_id", mUserId); 
       connection.addFormField("session_token", mSessionToken); 
       connection.addFilePart("profile_picture", mProfilePicture); 
       String result = connection.finish(); 
       Log.d("PROFILE PICTURE", result); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

답변

1

는 다중 필요하다? POST 요청으로 하나의 파일 만 보내야하는 경우 연결의 출력 스트림에 이진 데이터를 간단하게 쓸 수 있습니다. (필자는 PHP에 대한 경험이 없지만 PHP가 요청 본문을 읽을 수 있다고 가정합니다.) 다른 필드는 쿼리 매개 변수 또는 HTTP 헤더로 전송 될 수 있습니다.

또한 Fiddler2와 같은 로깅 프록시를 통해 HTTP 트래픽을 라우팅하여 실제로 HTTP 요청 본문이 무엇인지 확인하고 (작동 테스트 예제와 비교하는 것이 좋습니다).

+0

당신이 제안처럼 내 매개 변수를 쿼리하는 데 사용하고 난 단지 전송 한 파일이 어디 솔루션이 경우에 참으로 허용 될 것이다. 하지만 하나의 파일을 여러 개 보내야 할 경우를 대비하여 Multipart를 사용하는 것이 내 목표입니다. 필자가 제안한 것처럼 Fiddler2를 사용하고 있지만 Multipart가 올바르게 포맷 된 것 같습니다. 아마도 FileInputStream이 잘못 작성된 것 같습니다. – user3850659

0

마침내 문제가 발견되었습니다. Fiddler2 Web Debugging 솔루션을 제공해 주셔서 감사합니다. 이 소프트웨어를 사용하여 서버 API를 테스트 할 수있는 유효한 HTTP 요청을 작성할 수있었습니다. 문제는 내 코드와 관련이 없습니다. PHP가 업로드 된 파일을받을 수없는 이유는 Google App Engine이 업로드 된 모든 파일을 자동으로 거부하기 때문입니다. 파일을 업로드하려면 먼저 업로드 URL을 만들어야합니다.

출처 : https://cloud.google.com/appengine/docs/php/googlestorage/user_upload