Android:上传文件,同时填写POST正文

时间:2012-01-22 21:50:33

标签: java php android file-upload multipartentity

我确实使用MultipartEntity将文件发送到服务器,它在$_FILES超全局中正确显示

但我还需要填写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的一部分,documentation

与此类似:Android: Uploading a file to a page along with other POST strings

1 个答案:

答案 0 :(得分:21)

只需向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
)

这并不会压缩一个内容正文部分内的所有后期变量,但它会使该作业正常工作。

您无法访问php://stdin$HTTP_RAW_POST_DATA中的数据,这两种数据都不可用于多部分/表单数据编码。来自PHP文档:

  

php:// input是一个只读流,允许您读取原始数据   来自请求机构。在POST请求的情况下,它是可取的   使用php://输入而不是$ HTTP_RAW_POST_DATA,因为它没有   依赖于特殊的php.ini指令。而且,对于那些情况   默认情况下不会填充$ HTTP_RAW_POST_DATA,它是潜在的   激活的内存密集程度较低   always_populate_raw_post_data。 php://输入不可用   ENCTYPE = “多部分/格式数据”。

即使您将always_populate_raw_post_data设置为开启,它仍然无法解决问题:

  

始终填充包含原始POST数据的$ HTTP_RAW_POST_DATA。   否则,仅使用无法识别的MIME类型填充变量   的数据。但是,访问原始POST的首选方法   数据是php://输入。 $ HTTP_RAW_POST_DATA不可用   ENCTYPE = “多部分/格式数据”。

我最好的猜测只是将所有数据添加为ByteArrayBodyStringBody 使用它就好像你正在阅读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并将所有数据放在一个post变量中,然后从中解析它,它会跳过将数据写入文件并在删除之后将其删除由于临时文件完全没用,因此这将提高性能。 这是一个例子:

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']);