如何使用 asynctask 将图像从 android 上传到 php

Posted

技术标签:

【中文标题】如何使用 asynctask 将图像从 android 上传到 php【英文标题】:How to upload an image from android to php using asynctask 【发布时间】:2017-03-08 16:47:27 【问题描述】:

每个人。我被困在我正在从事的这个项目上。我希望能够从 android 库上传图像,将该图像编码为 base64 字符串并作为 get 变量发送到 php Web 服务,然后从另一端解码图像并按照我的意愿进行处理。

到目前为止,我能够从图库中选择图像,甚至可以编码为 base64 字符串并存储在 android 首选项中。

问题是,我认为并非所有字符串都被发送到 PHP 服务(有些被截断)。

我为什么这么认为?我的 Log.d 在转储到不同位置时向我显示了不同的字符串。

获取图像并编码的代码是:-

private void galleryIntent()

    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Please select a file"),1);


private String onSelectFromGalleryResult (Intent data) 

    if (data != null) 
        try 
            bitmap = MediaStore.Images.Media.getBitmap(getContext().getContentResolver() , data.getData()) ;
         catch (IOException e) 
            e.printStackTrace();
        

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream() ;

        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream) ;

        byte[] imageBytes = byteArrayOutputStream.toByteArray() ;

        Log.d ("Selected Image Gallery" , Base64.encodeToString(imageBytes, Base64.DEFAULT)) ;

        return Base64.encodeToString (imageBytes, Base64.DEFAULT) ;
     else 
        return null ;
    


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);

    SharedPreferences sharedPreferences =  getContext().getSharedPreferences("MyOnActivityResultPref" , Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit() ;

    if (resultCode == Activity.RESULT_OK) 

        if (requestCode == 1) 
            /*Here we handle the image gotten from the gallery*/
            String encodedGalleryImage = onSelectFromGalleryResult(data);

           editor.putString("userEncodedGalleryImage" , encodedGalleryImage);

         else if (requestCode == 0) 
            /*Here we handle the image that was take using the camera*/

        

        editor.apply();
    

这里我们称之为 asynctask 类

private void callAsynctask () 
  SharedPreferences sp = getContext().getSharedPreferences("MyOnActivityResultPref" , Context.MODE_PRIVATE);

    String userQuestionAttachement = sp.getString("userEncodedGalleryImage" , "") ;

Log.d("callingEncodedImage" , userQuestionAttachement) ;

我遇到的问题是来自 Log.d ("Selected Image Gallery" , Base64.encodeToString(imageBytes, Base64.DEFAULT)) 的日志;与 Log.d("callingEncodedImage" , userQuestionAttachement) 不同;

两者的开头相同,但结尾不同。我希望看到相同的字符。

有人可以帮我解决吗?

【问题讨论】:

base64 字符串有时可能太大而无法一次性发送。更好的选择是使用多部分上传图像文件。 你好@VivekMishra 你会怎么做?我想这就是我需要的!... 【参考方案1】:

在 Android 中,

 new UploadFileAsync().execute("");



  private class UploadFileAsync extends AsyncTask<String, Void, String> 

    @Override
    protected String doInBackground(String... params) 

        try 
  String sourceFileUri = "/mnt/sdcard/abc.png";

            HttpURLConnection conn = null;
            DataOutputStream dos = null;
            String lineEnd = "\r\n";
            String twoHyphens = "--";
            String boundary = "*****";
            int bytesRead, bytesAvailable, bufferSize;
            byte[] buffer;
            int maxBufferSize = 1 * 1024 * 1024;
            File sourceFile = new File(sourceFileUri);

            if (sourceFile.isFile()) 

                try 
                    String upLoadServerUri = "http://website.com/abc.php?";

                    // open a URL connection to the Servlet
                    FileInputStream fileInputStream = new FileInputStream(
                            sourceFile);
                    URL url = new URL(upLoadServerUri);

                    // Open a HTTP connection to the URL
                    conn = (HttpURLConnection) url.openConnection();
                    conn.setDoInput(true); // Allow Inputs
                    conn.setDoOutput(true); // Allow Outputs
                    conn.setUseCaches(false); // Don't use a Cached Copy
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("Connection", "Keep-Alive");
                    conn.setRequestProperty("ENCTYPE",
                            "multipart/form-data");
                    conn.setRequestProperty("Content-Type",
                            "multipart/form-data;boundary=" + boundary);
                    conn.setRequestProperty("bill", sourceFileUri);

                    dos = new DataOutputStream(conn.getOutputStream());

                    dos.writeBytes(twoHyphens + boundary + lineEnd);
                    dos.writeBytes("Content-Disposition: form-data; name=\"bill\";filename=\""
                            + sourceFileUri + "\"" + lineEnd);

                    dos.writeBytes(lineEnd);

                    // create a buffer of maximum size
                    bytesAvailable = fileInputStream.available();

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

                    // read file and write it into form...
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                    while (bytesRead > 0) 

                        dos.write(buffer, 0, bufferSize);
                        bytesAvailable = fileInputStream.available();
                        bufferSize = Math
                                .min(bytesAvailable, maxBufferSize);
                        bytesRead = fileInputStream.read(buffer, 0,
                                bufferSize);

                    

                    // send multipart form data necesssary after file
                    // data...
                    dos.writeBytes(lineEnd);
                    dos.writeBytes(twoHyphens + boundary + twoHyphens
                            + lineEnd);

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

                    if (serverResponseCode == 200) 

                        // messageText.setText(msg);
                        //Toast.makeText(ctx, "File Upload Complete.",
                        //      Toast.LENGTH_SHORT).show();

                        // recursiveDelete(mDirectory1);

                    

                    // close the streams //
                    fileInputStream.close();
                    dos.flush();
                    dos.close();

                 catch (Exception e) 

                    // dialog.dismiss();
                    e.printStackTrace();

                
                // dialog.dismiss();

             // End else block


         catch (Exception ex) 
            // dialog.dismiss();

            ex.printStackTrace();
        
        return "Executed";
    

    @Override
    protected void onPostExecute(String result) 

    

    @Override
    protected void onPreExecute() 
    

    @Override
    protected void onProgressUpdate(Void... values) 
    

在 PHP 中,

    <?php


     if (is_uploaded_file($_FILES['bill']['tmp_name'])) 
    $uploads_dir = './';
                            $tmp_name = $_FILES['bill']['tmp_name'];
                            $pic_name = $_FILES['bill']['name'];
                            move_uploaded_file($tmp_name, $uploads_dir.$pic_name);
                            
               else
                   echo "File not uploaded successfully.";
           

   ?>

【讨论】:

你好@Magash。我已经有一个 Asynctask 代码和一个 PHP 服务,我的问题介于两者之间,编码的字符串被截断。我不知道为什么... 感谢您提供 PHP 代码!这对我有用。我确实向扩展的 AsyncTask 类添加了一个构造函数,它将输入文件路径和 IP 地址作为参数。通过这个微小的更改,代码按预期工作。【参考方案2】:

要使用 Multipart 上传图片,请按以下步骤操作:

    下载 httpmime.jar 文件并将其添加到您的 libs 文件夹中。

    下载 http client.jar 文件并将其添加到您的 libs 文件夹中。

从后台线程或 AsyncTask 调用以下方法。

public void executeMultipartPost() throws Exception 
    try 
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bm.compress(CompressFormat.JPEG, 75, bos);
        byte[] data = bos.toByteArray();
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost postRequest = new HttpPost(
                "YOUR SERVER URL");
        ByteArrayBody bab = new ByteArrayBody(data, "YOUR IMAGE.JPG");

        MultipartEntity reqEntity = new MultipartEntity(
                HttpMultipartMode.BROWSER_COMPATIBLE);
        reqEntity.addPart("IMAGE", bab);

        postRequest.setEntity(reqEntity);
        HttpResponse response = httpClient.execute(postRequest);
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                response.getEntity().getContent(), "UTF-8"));
        String sResponse;
        StringBuilder s = new StringBuilder();

        while ((sResponse = reader.readLine()) != null) 
            s = s.append(sResponse);
        
        System.out.println("Response: " + s);
     catch (Exception e) 
        // handle exception here
        Log.e(e.getClass().getName(), e.getMessage());
    

【讨论】:

以上是关于如何使用 asynctask 将图像从 android 上传到 php的主要内容,如果未能解决你的问题,请参考以下文章

如果使用 Asynctask 将 URL 存储在 ArrayList 中,如何从服务器下载图像?

如何从服务器下载图像如果使用Asynctask存储在ArrayList中的URL?

Android:使用 Asynctask 从 Web 加载图像

如何将 Asynctask 用于位图?

使用 AsyncTask 从 ImageView 上传带有字符串值的图像

如何在 Android Studio 中使用 AsyncTask 从可绘制对象中设置图像