使用Android和PHP将照片存储为Blob

时间:2018-03-28 15:22:30

标签: php android image blob

我目前正在开发一个处理图片并将其上传到数据库的Android应用程序。 应用程序首先使用设备的摄像头,然后将生成的Bitmap发送到AsyncTask,AsyncTask将调用PHP API以图像作为mediumBLOB和附加数据(int和String)更新数据库。

AsyncTask将Bitmap编码为String,并将所有需要的数据作为POST请求发送到PHP页面。

PHP页面然后收集数据,将String转换为BLOB映像,并在mysqli请求中使用它们在数据库表中插入新行。

更新:感谢您的反馈。我改变了PHP代码,使用绑定变量。 虽然,当我将图像设置为参数时,请求会生成一个带有空BLOB的新表行。 我知道通常的方法是在其他地方存储图像并在数据库中使用它们的名称/ URL;但在我的情况下,使用BLOB是一项要求。

以下是AsyncTask的Android代码:

public class DBTaskImageSending extends AsyncTask<String, Void, Void>
{
    static final String TAG = "asyncSend";

    private final String PARAMETER_PLACE = "location";
    private final String PARAMETER_IMAGE = "image";
    private final String PARAMETER_COMMENT = "comment";
    private final String PARAMETER_OWNER = "owner";

    Context mCContext;
    UploadActivity mUAMain;

    //The PHP page address :
    String mURLAdress;

    //Data to send to the PHP page :
    String mComment;
    int mID_Photographer;
    int mID_Event;
    String mImage; //The image in its final conversion before sending it.

    public DBTaskImageSending(String url, UploadActivity ua, Context c, Bitmap img, String comment, int place, int owner)
    {
        this.mURLAdress = url;
        this.mCContext = c;
        this.mUAMain = ua;

        this.mComment = comment;
        this.mID_Event = place;
        this.mID_Photographer = owner;
        this.mImage = conv_Image_String(img);
    }

    @Override
    protected void onPreExecute()
    {
        super.onPreExecute();
        Log.i(TAG, "Request sent to "+mURLAdress);
    }

    @Override
    protected void onPostExecute(Void result)
    {
        Log.i(TAG,"__________________________________________________");
        super.onPostExecute(result);
    }

    @Override
    protected Void doInBackground(String... strings)
    {
        try
        {
            sendImage(mURLAdress);
            Log.i(TAG, "Object sent !");
        }
        catch (IOException ioe)
        {
            Log.i(TAG, "Sending failed.");
        }
        return null;
    }

    public void sendImage(String url) throws IOException
    {
        //Loading the POST data :
        String mSCryptedData = URLEncoder.encode(PARAMETER_PLACE, "UTF-8")
                + "=" + URLEncoder.encode(Integer.toString(mID_Event), "UTF-8");
        //----- owner ID :
        mSCryptedData += "&" + URLEncoder.encode(PARAMETER_OWNER, "UTF-8")
                + "=" + URLEncoder.encode(Integer.toString(mID_Photographer), "UTF-8");
        //----- Image comments :
        mSCryptedData += "&" + URLEncoder.encode(PARAMETER_COMMENT, "UTF-8")
                + "=" + URLEncoder.encode(mComment, "UTF-8");
        //----- the image itself :
        mSCryptedData += "&" + URLEncoder.encode(PARAMETER_IMAGE, "UTF-8")
                + "=" + URLEncoder.encode(mImage,"UTF-8");//*/

        ContentValues mCV = new ContentValues();
        mCV.put(PARAMETER_PLACE,mID_Event);
        mCV.put(PARAMETER_OWNER,mID_Photographer);
        mCV.put(PARAMETER_COMMENT,mComment);
        mCV.put(PARAMETER_IMAGE,mImage);

        try {
            //Eestablishing connection :
            final HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setReadTimeout(5000); // milliseconds
            conn.setConnectTimeout(5000); // milliseconds

            //Setting up and sending the data :
            conn.setDoOutput(true);
            OutputStreamWriter mOSW = new OutputStreamWriter(conn.getOutputStream());
            mOSW.write(mSDataCryptee);
            mOSW.flush();

            //Gathering the server's response:
            readResponse(conn.getInputStream());
        }
        catch (Exception e)
        {
            Log.i(TAG,e.getCause().toString());
        }
    }

    private void readResponse(InputStream pISBuilder) throws IOException
    {
        Log.i(TAG,"readR : Entering...");
        BufferedReader mBR = new BufferedReader(new InputStreamReader(pISBuilder));
        String ligne;

        Log.i(TAG,"readR : Starting to read");
        //Gathering the PHP response :
        while ((ligne = mBR.readLine()) != null)
        {
            Log.i(TAG,ligne);
        }
    }

    //* Function to convert the Bitmap to String :
    private String conv_Image_String(Bitmap imgOrigin)
    {
        if (imgOrigin != null)
        {
            //The image is first converted to byte[] (or Blob), before being encoded to String.
            ByteArrayOutputStream mBOS = new ByteArrayOutputStream();
            imgOrigin.compress(Bitmap.CompressFormat.PNG,10, mBOS);
            byte[] mBytImg = mBOS.toByteArray();

            String mStrImg = Base64.encodeToString(mBytImg, Base64.DEFAULT);
            return mStrImg;
        }
        else
        {
            return null;
        }
    }//*/

}

我重新编写了PHP代码,所以这是新版本:

<?php
if ((isset($_POST['location']) AND isset($_POST['owner'])) AND (isset($_POST['comment']) AND isset($_POST['image']))) {
    $location = $_POST['location'];
    $comment = $_POST['comment'];
    $owner = $_POST['owner'];
    $image = base64_decode($_POST['image']);

    $image_b = imagecreatefromstring($image);

    //*
    if ($image_b == false) {
        echo "error_image";
    }
    else {

        $image_temp = imagegd($image_b, 'tmp');
        $image_f = fopen('tmp',"r");
        $image_blob = fread($image_f,filesize('tmp'));

        sendData ($location,$comment,$owner,$image_blob);
    }
}
else {
    echo "error_parameters";
}

function sendData($p_location,$p_comment,$p_owner,$p_image){
    $conn = mysqli_connect("localhost", "****", "****", "**DBName**", "3306");
    if (!$conn) {
        die('Could not connect to MySQL: ' . mysqli_connect_error());
    }
    else {
        mysqli_query($conn, 'SET NAMES \'utf8\'');
        $sqli = "INSERT INTO bar_a_image_test.Photo(
            ID_Localisation_Photo,
            ID_Photographe,
            Date_Photo,
            Ecartee,
            Commentaire_Photo,
            Image_Photo)
        VALUES
            ( ? , ? , NULL, 0, ?, ? )";

        if ($stmt = $conn->prepare($sqli));
        {
            $stmt->bind_param("iisb",$p_location, $p_owner, $p_comment, $p_image);
            $stmt->execute();
        }
        $conn->close();
    }
}
?>

现在的新问题是查询加载数据库中的所有数据,但图像除外。它只是在新行中记录一个空BLOB。 我正在寻找一种有效地将图像(编码为字符串)转换为BLOB的方法。 正如我之前提到的,我必须使用BLOB,尽管外部存储更频繁。

1 个答案:

答案 0 :(得分:0)

感谢@Gabe Sechan建议我使用bind_param,我最终找到了解决方案。 它全部在bind_param声明中:

$stmt->bind_param("iisb",$p_location, $p_owner, $p_comment, $p_image);

我没有将解码图像声明为Blob(第一个参数末尾的“b”),而是将其声明为字符串(将“b”替换为“s”)。 以这种方式调用方法:

$stmt->bind_param("iiss",$p_location, $p_owner, $p_comment, $p_image);

图像在数据库中作为Blob完美加载。 感谢您的支持!