【问题标题】:How to read Android HttpURLConnection multipart stream in PHP - sending an image file to server如何在 PHP 中读取 Android HttpURLConnection 多部分流 - 将图像文件发送到服务器
【发布时间】:2016-05-17 04:51:55
【问题描述】:

我讨厌发布像这样很长的代码示例,但我就是不知道为什么它不起作用,所以我唯一能想到的就是分享这些烂摊子。

我在这里遵循本指南: http://www.coderefer.com/android-upload-file-to-server/

我正在通过 webview 处理它,因此我必须对界面部分的工作方式进行一些更改,并且我必须添加一些代码以获得权限,因为我在 Marshmallow 上:

ActivityCompat.requestPermissions(this,
                                new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

但据我所知,一切都在 android 活动上正常工作,因为现在我获得了权限,因此我没有收到任何错误。

我在这里将我能够成功收集的路径传递给这个函数:

public int uploadFile(final String selectedFilePath){

    int serverResponseCode = 0;

    HttpURLConnection connection;
    DataOutputStream dataOutputStream;
    String lineEnd = "\r\n";
    String twoHyphens = "--";
    String boundary = "*****";


    int bytesRead,bytesAvailable,bufferSize;
    byte[] buffer;
    int maxBufferSize = 1 * 1024 * 1024;
    File selectedFile = new File(selectedFilePath);


    String[] parts = selectedFilePath.split("/");
    final String fileName = parts[parts.length-1];

    if (!selectedFile.isFile()){
       // dialog.dismiss();

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this,"Source File Doesn't Exist: " + selectedFilePath,Toast.LENGTH_SHORT).show();
            }
        });
        return 0;
    }else{
        try{
            FileInputStream fileInputStream = new FileInputStream(selectedFile);
            URL url = new URL(SERVER_URL);
            connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);//Allow Inputs
            connection.setDoOutput(true);//Allow Outputs
            connection.setUseCaches(false);//Don't use a cached Copy
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("ENCTYPE", "multipart/form-data");
            connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
            connection.setRequestProperty("uploaded_file",selectedFilePath);

            //creating new dataoutputstream
            dataOutputStream = new DataOutputStream(connection.getOutputStream());

            //writing bytes to data outputstream
            dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
            dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""
                    + selectedFilePath + "\"" + lineEnd);

            dataOutputStream.writeBytes(lineEnd);

            //returns no. of bytes present in fileInputStream
            bytesAvailable = fileInputStream.available();
            //selecting the buffer size as minimum of available bytes or 1 MB
            bufferSize = Math.min(bytesAvailable,maxBufferSize);
            //setting the buffer as byte array of size of bufferSize
            buffer = new byte[bufferSize];

            //reads bytes from FileInputStream(from 0th index of buffer to buffersize)
            bytesRead = fileInputStream.read(buffer,0,bufferSize);

            //loop repeats till bytesRead = -1, i.e., no bytes are left to read
            while (bytesRead > 0){
                //write the bytes read from inputstream
                dataOutputStream.write(buffer,0,bufferSize);
                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable,maxBufferSize);
                bytesRead = fileInputStream.read(buffer,0,bufferSize);
            }

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

            serverResponseCode = connection.getResponseCode();
            String serverResponseMessage = connection.getResponseMessage();

            final String  result = getStringFromInputStream(connection.getInputStream());
            //Log.i(TAG, "Server Response is: " + serverResponseMessage + ": " + serverResponseCode);

            //response code of 200 indicates the server status OK
            if(serverResponseCode == 200){
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,result,Toast.LENGTH_SHORT).show();
                    }
                });
            }

            //closing the input and output streams
            fileInputStream.close();
            dataOutputStream.flush();
            dataOutputStream.close();



        } catch (FileNotFoundException e) {
            e.printStackTrace();
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this,"File Not Found",Toast.LENGTH_SHORT).show();
                }
            });
        } catch (MalformedURLException e) {
            e.printStackTrace();
            Toast.makeText(MainActivity.this, "URL error!", Toast.LENGTH_SHORT).show();

        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(MainActivity.this, "Cannot Read/Write File!", Toast.LENGTH_SHORT).show();
        }
       // dialog.dismiss();
        return serverResponseCode;
    }

}

我能够使用他的 php 方法从我的服务器返回“失败”响应:

$file_path = "uploads/";

$file_path = $file_path . basename( $_FILES['uploaded_file']['name']);
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path) ){
    echo "success";
} else{
    echo "fail";
}
?>

但是,在我看来 $_FILES['uploaded_file'] 是空的,因为我每次都会收到失败作为响应。当我在其上使用 var_dump($_FILES['uploaded_file']) 时,我从输入流中得到了它为空的 toast 消息。什么都没有得救。我正在尝试发送不超过 100kb 的小图片,并且可以通过浏览器上传图片。

非常感谢您提供任何帮助,感谢您的宝贵时间!

【问题讨论】:

  • ini_set('memory_limit', '512M');987654325@等php文件中添加文件大小限制
  • 如果没有成功,然后尝试从android代码中删除connection.setRequestProperty("ENCTYPE", "multipart/form-data");connection.setRequestProperty("uploaded_file",selectedFilePath);行。
  • 感谢您的回复。我尝试了这两种方法,但不幸的是没有成功。仍然从我的 var 转储中获取 null。
  • 尝试将 end dataOutputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); 替换为 dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
  • 那里也没有运气。

标签: php android stream httpurlconnection


【解决方案1】:

试试下面的文件上传类

import android.util.Log;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import in.gauriinfotech.sevadeal.constants.RestConstants;

/**
 * Created by NiRRaNjAN on 23/02/2016.
 */
public class FileUploader implements RestConstants {

    public static String sendFileToServer(File filename, String targetUrl, String vendorId, String type) {
        String response = "error";
        HttpURLConnection connection = null;
        DataOutputStream outputStream = null;

        String urlServer = targetUrl;
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";

        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int maxBufferSize = 512;
        try {
            Log.e(tag, "+++++++++++ FILE NAME TO UPLOAD :: " + filename.getAbsolutePath());
            FileInputStream fileInputStream = new FileInputStream(filename);
            Log.e(tag, "++++++++++++ FILE LENGTH :: " + (filename.length()/1024d) + " Kbytes");
            URL url = new URL(urlServer);
            connection = (HttpURLConnection) url.openConnection();

            // Allow Inputs & Outputs
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);
//            connection.setChunkedStreamingMode(1024);
            // Enable POST method
            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);

            String connstr = null;
            connstr = "Content-Disposition: form-data; name=\""+FILE+"\";filename=\""
                    + filename.getName() + "\"" + lineEnd;
            Log.i("Connstr", connstr);

            outputStream.writeBytes(connstr);
            outputStream.writeBytes(lineEnd);

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

            // Read file
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
            Log.e("Image length", bytesAvailable + "");
            try {
                while (bytesRead > 0) {
                    try {
                        outputStream.write(buffer, 0, bufferSize);
                    } catch (OutOfMemoryError e) {
                        e.printStackTrace();
                        response = "outofmemoryerror";
                        return response;
                    }
                    bytesAvailable = fileInputStream.available();
                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                }
            } catch (Exception e) {
                e.printStackTrace();
                response = "error";
                return response;
            }
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);
            /*
            Upload String parameters
            * */
            Log.e(tag, "++++++++++++ FILE UPLOAD SUCCESS. SENDING TYPE " + type);
            outputStream.writeBytes("Content-Disposition: form-data; name=\"" + TYPE + "\"" + lineEnd);
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(type);
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);

            Log.e(tag, "++++++++++++ TYPE sending succes. Sending VENDOR ID");
            outputStream.writeBytes("Content-Disposition: form-data; name=\"" + USER_ID + "\"" + lineEnd);
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(vendorId);
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);

            Log.e(tag, "++++++++++++ VENDOR ID sent success.");
            int serverResponseCode = connection.getResponseCode();
            String serverResponseMessage = connection.getResponseMessage();
            Log.i("Server Response Code ", "+++++++++++ SERVER RESPONSE CODE :: " + serverResponseCode);
            Log.i("Server Response Message", "+++++++++++ RESPONSE MESSAGE :: '" + serverResponseMessage + "'");
            if (serverResponseCode == 200) {
                response = "true";
            } else {
                try {
                    InputStream inputStream = connection.getErrorStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                    String line;
                    StringBuilder builder = new StringBuilder();
                    while((line = reader.readLine()) != null) {
                        builder.append(line);
                    }
                    reader.close();
                    Log.e(tag, "++++++++++++ RETURN ERROR FROM SERVER +++++++");
                    Log.e(tag, builder.toString());
                } catch (Exception ex) {
                    Log.e(tag, Log.getStackTraceString(ex));
                }
            }
            fileInputStream.close();
            outputStream.flush();
            outputStream.close();
//            outputStream = null;
        } catch (Exception ex) {
            // Exception handling
            response = "error";
            Log.e("Send file Exception", ex.getMessage() + "");
            ex.printStackTrace();
        }
        return response;
    }

}

在服务器端,通过更改一些功能添加以下代码

<?php
require_once('conn.php');
ini_set('display_errors', 'on');
ini_set('memory_limit', '512M');
date_default_timezone_set("Asia/Calcutta");
$response = array();
$uploadFileName  = $_FILES[$FILE]['name'];
$info = pathinfo($uploadFileName);
$ext = $info['extension'];
$response[$VENDOR_ID] = $_POST[$VENDOR_ID];
$response[$TYPE] = $_POST[$TYPE];
$response["size"] = $_FILES[$FILE]['size'];
if(isset($_POST[$TYPE]) && $_FILES[$FILE]['size'] > 0 && isset($_POST[$VENDOR_ID])) {
    $mysqli     = Database::getInstance();
    $date = date("d_m_Y_h_i_s_A.");
    $type = $_POST[$TYPE];
    $vendorID = $_POST[$VENDOR_ID];
    if(!is_dir($PROFILE_FOLDER)) {
        mkdir($PROFILE_FOLDER);
    }
    if(!is_dir($IMAGES_FOLDER)) {
        mkdir($IMAGES_FOLDER);
    }
    if(!is_dir($VIDEOS_FOLDER)) {
        mkdir($VIDEOS_FOLDER);
    }
    $fileName;
    $query;
    if($type == $PROFILE_PIC) {
        $fileName = $PROFILE_FOLDER . $date . $ext;
        $query = "UPDATE $PROFILE_PIC SET $PICTURE_PATH=? WHERE $VENDOR_ID=?";
    } else if($type == $IMAGES) {
        $fileName = $IMAGES_FOLDER . $date . $ext;
        $query = "INSERT INTO $PROMOTIONAL_PIC ($PICTURE_PATH, $VENDOR_ID) VALUES (?,?)";
    } else if($type == $VIDEOS) {
        $fileName = $VIDEOS_FOLDER . $date . $ext;
        $query = "INSERT INTO $PROMOTIONAL_VIDEO ($VIDEO_PATH, $VENDOR_ID) VALUES (?,?)";
    } else {
        $response[$STATUS] = "Type $type not supported. ";
        echo json_encode($response);
        exit();
    }
    $tmpName  = $_FILES[$FILE]['tmp_name'];
/*  $fp      = fopen($tmpName, 'r');
    $content = fread($fp, filesize($tmpName));
    fclose($fp);

    $fp = fopen($fileName, 'w');

    if(fwrite($fp, $content)) {*/
    if(move_uploaded_file($tmpName, $fileName)) {
        $stmt = $mysqli->prepare($query);
        $stmt->bind_param('ss', $fileName, $vendorID);
        if($stmt->execute()) {
            $response[$STATUS] = $SUCCESS;
        } else {
            $response[$STATUS] = "Failed to inesrt into database. " . mysqli_error($mysqli);
        }
    } else {
        $response[$STATUS] = "Failed to write file.";
    }
    $content = addslashes($content);
} else {
    $response[$STATUS] = "Invalid input";
}
echo json_encode($response);
?>

注意:我在 php 文件中使用了一些常量,这些常量在 conn.php 文件中声明。例如$FILE, $STATUS, $SUCCESS, etc.

【讨论】:

  • 我需要一些额外的文件吗? in.gauriinfotech.sevadeal.constants.RestConstants;
  • 不...只需通过变量名更改常量...例如在您的情况下,$FILE 应替换为 uploaded_file
猜你喜欢
  • 1970-01-01
  • 2017-06-30
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多