Android: загрузить файл с заполнением тела POST - PullRequest
2 голосов
/ 23 января 2012

Я использую MultipartEntity для отправки файла на сервер, он отображается правильно в $_FILES superglobal

Но мне нужно также заполнить тело POST для чтения через php://stdin

Как можноЯ делаю это?

текущий фрагмент ниже:

ByteArrayOutputStream bos = new ByteArrayOutputStream(); // stream to hold image
bm.compress(CompressFormat.JPEG, 75, bos); //compress image
byte[] data = bos.toByteArray(); 
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("REMOTE ADDRESS");
ByteArrayBody bab = new ByteArrayBody(data, "image.jpg");
MultipartEntity reqEntity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE); // is this one causing trouble?
reqEntity.addPart("image", bab); // added image to request
// tried this with no luck
// reqEntity.addPart("", new StringBody("RAW DATA HERE")); 
postRequest.setEntity(reqEntity); // set the multipart entity to http post request
HttpResponse response = httpClient.execute(postRequest);

MultipartEntity является частью HttpMime 4.1.2 API, документация

Аналогично этому: Android: загрузка файла на страницу вместе с другими строками POST

1 Ответ

21 голосов
/ 25 января 2012

Просто добавьте несколько FormBodyPart к вашему MultipartEntity.

. Вы можете использовать объект StringBody для предоставлениязначение.

Вот пример того, как вы можете его использовать:

byte[] data = {10,10,10,10,10}; 
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("server url");
ByteArrayBody bab = new ByteArrayBody(data, "image.jpg");
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("image", bab);

FormBodyPart bodyPart=new FormBodyPart("formVariableName", new StringBody("formValiableValue"));
reqEntity.addPart(bodyPart);
bodyPart=new FormBodyPart("formVariableName2", new StringBody("formValiableValue2"));
reqEntity.addPart(bodyPart);
bodyPart=new FormBodyPart("formVariableName3", new StringBody("formValiableValue3"));
reqEntity.addPart(bodyPart); 
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = null;
while((line = in.readLine()) != null) {
    System.out.println(line);
}

Вот вывод PHP-скрипта:

$_FILES
Array
(
    [image] => Array
        (
            [name] => image.jpg
            [type] => application/octet-stream
            [tmp_name] => /tmp/php6UHywL
            [error] => 0
            [size] => 5
        )

)
$_POST:
Array
(
    [formVariableName] => formValiableValue
    [formVariableName2] => formValiableValue2
    [formVariableName3] => formValiableValue3
)

Это не 't сжать все записи внутри одной части тела контента, но это дозирует задание.

Вы не можете получить доступ к данным из php: // stdin или $ HTTP_RAW_POST_DATA , оба недоступны для многократного кодирования / кодирования данных формы.Из PHP документации:

php: // input - это поток только для чтения, который позволяет вам читать необработанные данные из тела запроса.В случае запросов POST предпочтительнее использовать php: // input вместо $ HTTP_RAW_POST_DATA, поскольку это не зависит от специальных директив php.ini.Более того, для тех случаев, когда $ HTTP_RAW_POST_DATA не заполняется по умолчанию, это потенциально менее ресурсоемкая альтернатива активации Always_populate_raw_post_data.php: // ввод недоступен с enctype = "multipart / form-data".

Даже если вы установите для always_populate_raw_post_data значение On, он все равно не исправитпроблема:

Всегда заполняйте $ HTTP_RAW_POST_DATA, содержащий необработанные данные POST.В противном случае переменная заполняется только нераспознанным типом данных MIME.Однако предпочтительным способом доступа к необработанным данным POST является php: // input.$ HTTP_RAW_POST_DATA недоступно с enctype = "multipart / form-data".

Лучше всего просто добавить все данные как ByteArrayBody или StringBody и просто используйте это, как если бы вы читали с php: // stdin

Вот пример ByteArrayBody:

String testString="b=a&c=a&d=a&Send=Send";
reqEntity.addPart(new FormBodyPart("formVariables", new ByteArrayBody(testString.getBytes(), "application/x-www-form-urlencoded", "formVariables")));

И в PHP:

var_dump(file_get_contents($_FILES['formVariables']['tmp_name']));

Вы должны получить:

string (21) "b = a & c = a & d = a & Send = Send"

Редактировать: После некоторых раздумий я думаю, что лучше просто использовать одну StringBody и поместить все данные в одну переменную записи, а затем проанализировать ее, пропуская запись данных в файл и удалениепосле запроса, поскольку временный файл полностью бесполезен, это увеличит производительность.Вот пример:

String testString="b=a&c=a&d=a&Send=Send";
bodyPart=new FormBodyPart("rawData", new StringBody(testString));
reqEntity.addPart(bodyPart);

Затем из PHP:

var_dump($_POST['rawData']);
...