使用来自 Android 应用程序的文件和文本发出 POST 请求

Make a POST request with file and text from an Android application

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

当我尝试从 Android 发送图像时,它 returns 收到“200 OK”响应,但图像未保存在 Google 云存储的存储桶中。我知道问题出在 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%正确的,所以你不用担心。

如果您需要查看来自网络服务的 PHP 代码以接收请求,这里是:

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

echo "done";

?>

此代码中的问题可能出在哪里?

额外

除了file/image,我还需要添加一些文字。如何将此添加到请求中?

为什么不使用 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

您发送的图像文件似乎丢失 Content-type

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

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

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

补充:除了file/image,我还需要添加一些文字。如何将此添加到请求中? 要发送一些额外的参数(一些文本),请查看以下发送图像和文本参数的 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

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