代码之家  ›  专栏  ›  技术社区  ›  John Toe

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

  •  0
  • John Toe  · 技术社区  · 7 年前

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

    AsyncTask将位图编码为字符串,并将所有需要的数据作为POST请求发送到PHP页面。

    然后PHP页面收集数据,将字符串转换为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 回复  |  直到 7 年前
        1
  •  0
  •   John Toe    7 年前

    感谢@Gabe Sechan建议我使用bind\u param,我最终找到了一个解决方案。 都在bind\u 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完美地加载到数据库中。 感谢您的支持!