【问题标题】:Make a POST request with file and text from an Android application使用来自 Android 应用程序的文件和文本发出 POST 请求
【发布时间】:2016-01-13 18:33:17
【问题描述】:

我在从我的 Android 应用程序向我的网络服务(Google Cloud 和 PHP)发出正确的 POST 请求时遇到一些问题。

当我尝试从 Android 发送图像时,它会返回“200 OK”响应,但该图像未保存在 Google Cloud Storage 的存储桶中。我知道问题出在我在 Android 应用程序中的方法发出的 POST 请求上,因为我已经用 Postman 进行了测试,并让它毫无问题地工作。所以我的应用程序的以下代码有问题:

public void uploadFile(String uploadUrl, String filename, String newFileName) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(new File(filename));

        URL url = new URL(uploadUrl);
        connection = (HttpURLConnection) url.openConnection();

        // Allow Inputs & Outputs.
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);

        // Set HTTP method to POST.
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

        outputStream = new DataOutputStream(connection.getOutputStream() );
        outputStream.writeBytes(twoHyphens + boundary + lineEnd);
        outputStream.writeBytes("Content-Disposition: form-data; name=\"img\";filename=\"" + filename + "\"" + lineEnd);
        outputStream.writeBytes(lineEnd);

        bytesAvailable = fileInputStream.available();
        bufferSize = Math.min(bytesAvailable, maxBufferSize);
        buffer = new byte[bufferSize];

        // Read file
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);

        while (bytesRead > 0) {
            outputStream.write(buffer, 0, bufferSize);
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        }

        outputStream.writeBytes(lineEnd);
        outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

        // Responses from the server (code and message)
        int serverResponseCode = connection.getResponseCode();
        String serverResponseMessage = connection.getResponseMessage();


        System.out.println(serverResponseMessage);
        System.out.println(serverResponseCode);


        fileInputStream.close();
        outputStream.flush();
        outputStream.close();
    }

我已经测试过所有参数都是 100% 正确的,所以你不必担心。

如果您需要从 Web 服务中查看 PHP 代码以接收请求,这里是:

<?php
$img = $_FILES['img']['tmp_name'];
move_uploaded_file($img, 'gs://routeimages/yeeeeeeees.jpg');

echo "done";

?>

这段代码的问题可能出在哪里?

附加

我还需要在文件/图像之外添加一些文本。如何将此添加到请求中?

【问题讨论】:

  • name=\"img\";filename=\"" 我看到路径中有一个分号。这是为什么?无论如何,对于图像上传用户多部分数据。此答案中的详细信息...stackoverflow.com/questions/21553507/…

标签: php android post httpurlconnection


【解决方案1】:

您发送的图片文件似乎缺少Content-type

查看以下用于发送文件的 HTTP Post 标头

Content-type: multipart/form-data, boundary=AaB03x
    --AaB03x
    content-disposition: form-data; name="pics", filename="file2.gif"
    Content-type: image/gif
    Content-Transfer-Encoding: binary

    ...contents of file2.gif...
    --AaB03x--

因此您需要在代码中添加Content-type 属性,如下所示:

outputStream = new DataOutputStream(connection.getOutputStream() );
outputStream.writeBytes(twoHyphens + boundary + lineEnd); 
outputStream.writeBytes("Content-Disposition: form-data; name=\"img\";filename=\"" + filename + "\"" + lineEnd);
outputStream.writeBytes("Content-type: image/gif" + lineEnd); // or whatever format you are sending.
outputStream.writeBytes("Content-Transfer-Encoding: binary" + lineEnd); 
outputStream.writeBytes(lineEnd);

我希望这段代码可以帮助您解决问题。

附加:我还需要在文件/图像之外添加一些文本。如何将此添加到请求中? 要发送一些额外的参数(一些文本),请查看以下发送图像和文本参数的 http 格式:

    Content-type: multipart/form-data, boundary=AaB03x
    --AaB03x
    content-disposition: form-data; name="pics", filename="file2.gif"
    Content-type: image/gif
    Content-Transfer-Encoding: binary

    ...contents of file2.gif...
    --AaB03x--
    content-disposition: form-data; name="field1"

    Joe Blow
    --AaB03x

我希望你现在可以借助上面的图片上传说明和这种格式编写额外参数的代码。

【讨论】:

    【解决方案2】:

    为什么不使用 Volley 库?它的方式更容易和清洁。像这个例子:

    private void uploadImage(){
            //Showing the progress dialog
            final ProgressDialog loading = ProgressDialog.show(this,"Uploading...","Please wait...",false,false);
            StringRequest stringRequest = new StringRequest(Request.Method.POST, UPLOAD_URL,
                    new Response.Listener<String>() {
                        @Override
                    public void onResponse(String s) {
                        //Disimissing the progress dialog
                        loading.dismiss();
                        //Showing toast message of the response
                        Toast.makeText(MainActivity.this, s , Toast.LENGTH_LONG).show();
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError volleyError) {
                        //Dismissing the progress dialog
                        loading.dismiss();
    
                        //Showing toast
                        Toast.makeText(MainActivity.this, volleyError.getMessage().toString(), Toast.LENGTH_LONG).show();
                    }
                }){
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                //Converting Bitmap to String
                String image = getStringImage(bitmap);
    
                //Getting Image Name
                String name = editTextName.getText().toString().trim();
    
                //Creating parameters
                Map<String,String> params = new Hashtable<String, String>();
    
                //Adding parameters
                params.put(KEY_IMAGE, image);
                params.put(KEY_NAME, name);
    
                //returning parameters
                return params;
            }
        };
    
        //Creating a Request Queue
        RequestQueue requestQueue = Volley.newRequestQueue(this);
    
        //Adding request to the queue
        requestQueue.add(stringRequest);
    }
    

    Source

    【讨论】:

    • Liberi 感谢您的回答。非常感激。也许我稍后会考虑使用 Volley lib,但现在我将坚持使用“手动”方法。
    • 这是关于如何将文件转换为字符串然后发送字符串的一个很好的答案。但问题是如何发送文件。
    猜你喜欢
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 1970-01-01
    相关资源
    最近更新 更多