簡體   English   中英

在Android中進行多部分文件上傳的好方法

[英]A good approach to do multipart file upload in Android

我正在編寫一段代碼來執行多部分表單數據POST請求,在我的情況下,這只是將帶有參數的圖像上傳到服務器。 這是我現在所擁有的:

我有一個按鈕來觸發多部分請求,在按鈕OnClickListener中,我有以下代碼可以旋轉一個新線程:

new Thread(new Runnable(){

@Override
public void run() {

    String photoUri = getPhotoUri();
    String url = getEndPointUrl();

    try {   

    NewPostRequest.postFile(url, photoUri, <Other Params...>);

    } catch (Exception e) {
        // Exception Handling           
    } 
}).start();

NewPostRequest.postFile只是使用Apache Http Client發出請求,基本上如下:

HttpClient client = new DefaultHttpClient();

HttpPost post = new HttpPost(url);

MultipartEntityBuilder builder = MultipartEntityBuilder.create();    

builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);

File file = new File(fileUri);

FileBody fb = new FileBody(file);

builder.addPart("file", fb);

builder.addTextBody("param", otherParam);

HttpEntity entity = builder.build();

post.setEntity(entity);

HttpResponse response = client.execute(post);      

我需要每次旋轉一個新線程,因為最近的Android版本不允許程序在UI線程上發出http請求。 但是,我確實反對旋轉隨機線程並使其像上面的代碼一樣不受控制。 我曾嘗試使用Google Volley庫,但是在上傳大數據文件(如圖像)時,它並不是少數工具。

我想知道如何使此呼叫更易於管理?

=====更新=====

我切換為使用AsyncTask ,現在可以正常使用了。 我將繼續討論這個問題,看看是否有人有更好的方法。

HTTP一直是Android中的痛點。 幸運的是,我們有許多出色的庫可以處理所有困難的部分。

嘗試離子

它使您可以輕松地在后台線程中執行多部分請求,並讓您在請求完成時在主線程上獲得回調。

它還做其他很酷的事情,例如智能緩存,當調用上下文超出范圍時自動取消請求等。

PS: 翻新是另一個很棒的圖書館,但我更喜歡Ion本人。 只是一個偏好問題。

與將.db(任何擴展名)文件上傳到服務器有關的上述問題的解決方案:以下是上傳文件的步驟:

1:- new AsynUpload().execute();

2:-

class AsynUpload extends AsyncTask<Void,Integer,String>
        {
        String result="";
        ProgressDialog dialog=null;
        String iFileName = CONST.USER_NAME+".db";
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";
        String Tag="fSnd";

        @Override
        protected void onPreExecute()
        {
        Log.i("AsynUpload is callinmg...", "calling");
        dialog=new ProgressDialog(Upload_Database.this);
        dialog.setMessage("File uploading...");
        dialog.setCancelable(false);
        dialog.show();
        }

        @Override
        protected String doInBackground(Void... params) {
        try 
        {
        UTILITIES.copyDBToSDCard();
        String selectedFilePath = "/data/data/com.DxS.androidSunTec.visioapp/databases/"+CONST.USER_NAME+".db";
        FileInputStream fstrm = new FileInputStream(selectedFilePath);
        URL connectURL = new URL(CUSTOM_URL.UPLOAD_URL+"Default.aspx");
        HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();
        // Allow Inputs
        conn.setDoInput(true);
        // Allow Outputs
        conn.setDoOutput(true);
        // Don't use a cached copy.
        conn.setUseCaches(false);
        // Use a post method.
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
        conn.setRequestProperty("FILE_NAME", ""+CONST.USER_NAME+".db");
        DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
        dos.writeBytes(twoHyphens + boundary + lineEnd);
        dos.writeBytes("Content-Disposition: form-data; name=\"title\""+ lineEnd);
        dos.writeBytes(lineEnd);
        dos.writeBytes(""+CONST.USER_NAME);
        dos.writeBytes(lineEnd);
        dos.writeBytes(twoHyphens + boundary + lineEnd);                    
        dos.writeBytes("Content-Disposition: form-data; name=\"description\""+ lineEnd);
        dos.writeBytes(lineEnd);
        dos.writeBytes(loc_code+"~"+user_code+"~"+fyid);
        dos.writeBytes(lineEnd);
        dos.writeBytes(twoHyphens + boundary + lineEnd);
        dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + iFileName +"\"" + lineEnd);
        dos.writeBytes(lineEnd);

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

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

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

            while (bytesRead > 0)
            {
            dos.write(buffer, 0, bufferSize);
            bytesAvailable = fstrm.available();
            bufferSize = Math.min(bytesAvailable,maxBufferSize);
            bytesRead = fstrm.read(buffer, 0,bufferSize);
            }
            dos.writeBytes(lineEnd);
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

            // close streams
            fstrm.close();
            // 103424
            dos.flush();
            InputStream is = conn.getInputStream();

            // retrieve the response from server
            int ch;

            StringBuffer b =new StringBuffer();
            while( ( ch = is.read() ) != -1 ){ b.append( (char)ch ); }
            String s=b.toString();
            Log.i("Response",s);
            dos.close();

            result="OK";
            }

            catch (MalformedURLException ex)
            {
            result = "MalformedURLException";
            Log.i(Tag, "URL error: " + ex.getMessage(), ex);
            }
            catch (IOException ioe)
            {
            result = "IOException";
            Log.i(Tag, "IO error: " + ioe.getMessage(), ioe);
            }
            catch(Exception e)
            {
            Log.e("Exception","Exception"+e.getMessage());
            result="FAILURE";
            }
            finally
            {
            if (result.equalsIgnoreCase("OK"))
            {
            File file = new File("/data/data/com.test.app/databases/"+CONST.USER_NAME+".db");
                if(file.exists())
                {
                file.delete();
                Log.i("uploading database file Deleted from sd card :", "deleted");
                }
            file = new File("/data/data/com.test.app/databases/"+DatabaseHelper.DB_NAME);
                if(file.exists())
                {
                file.delete();
                Log.i("Original database file Deleted from sd card :", "deleted");
                }

                MyActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                    // TODO Auto-generated method stub
                    AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
                    LayoutInflater inflater = getLayoutInflater();
                    View vw = inflater.inflate(R.layout.custom_title, null);
                    builder.setCustomTitle(vw);
                    builder.setMessage("File uploaded successfully!")
                    .setCancelable(false)
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                            finish();
                            }
                        });
                            builder.create();
                            builder.show();
                            }
                        });
                        }
                    else
                    {
                    MyActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                        AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
                        LayoutInflater inflater = getLayoutInflater();
                        View vw = inflater.inflate(R.layout.custom_title, null);
                    builder.setCustomTitle(vw);
                    builder.setMessage("File uploading failed, please try again!")
                    .setCancelable(false)
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                                }
                            });
                                builder.create();
                                builder.show();
                                }
                            });
                            }
                              }
                            return result;
                        }   

                         @Override
                         protected void onProgressUpdate(Integer... values)
                         {
                             super.onProgressUpdate(values);
                         // dialog.incrementProgressBy(5);   
                        }
                        @Override
                        protected void onPostExecute(String result)
                        {
                            dialog.dismiss();

                            if (result.equalsIgnoreCase("OK"))
                            {
                            }
                            else
                            {
                            }
                        }
                      }

3.)UTILITIES類:

public static void copyDBToSDCard() {
        try {
            InputStream myInput = new FileInputStream("/data/data/com.DxS.androidSunTec.visioapp/databases/"+DatabaseHelper.DB_NAME);

            Log.i("sd card path: ", ""+Environment.getExternalStorageDirectory().getPath().toString());

        //    File file = new File(Environment.getExternalStorageDirectory().getPath()+"/"+CONST.USER_NAME+".db");
            File file = new File("/data/data/com.DxS.androidSunTec.visioapp/databases/"+CONST.USER_NAME+".db");
            if (!file.exists()){
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    Log.i("FO","File creation failed for " + file);
                }
            }

       //     OutputStream myOutput = new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/"+CONST.USER_NAME+".db");
            OutputStream myOutput = new FileOutputStream("/data/data/com.DxS.androidSunTec.visioapp/databases/"+CONST.USER_NAME+".db");

            byte[] buffer = new byte[1024];
            int length;
            while ((length = myInput.read(buffer))>0){
                myOutput.write(buffer, 0, length);
            }

            //Close the streams
            myOutput.flush();
            myOutput.close();
            myInput.close();
            Log.i("FO","copied");

        } catch (Exception e) {
            Log.i("FO","exception="+e);
        }
}

1)創建本機Android插件,用於與JSON對象一起上傳多個文件。 2)概念是分段文件上傳。 3)創建離線模式同步。 4)Phonegap和Android本機代碼。

Javascript調用本機Andorid代碼

alert(window.FilesUpload.sendFiles(JSON.stringify(jsonObj)));

以下是Android插件(FilesUpload.java)

package com.yourpackagename.core;
import java.io.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.json.JSONArray;
import org.json.JSONObject;


public class FilesUpload
{
   public FilesUpload() {

   }

   public String sendFiles(String s) {       


       String responseBody = "";

       try
       {

          JSONObject jsonObject = new JSONObject(s);   

          int len_outer = jsonObject.getJSONArray("electricityExpenseManagement").getJSONObject(0).length();

          HttpClient httpclient = new DefaultHttpClient();

          HttpPost httppost = new HttpPost("http://yourservername.com/php_file_upload/file_upload2.php");

          MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);          

          StringBody elecExpObj = new StringBody(s);

          reqEntity.addPart("elecExpObj", elecExpObj);



           for(int i=0;i<len_outer;i++)
           {
               int bill_count = jsonObject.getJSONArray("electricityExpenseManagement").getJSONObject(i).getJSONArray("electricityExpenseBillInfoData").length();

               for(int j=0;j<bill_count;j++)
               {
                   String sourceFileUri = jsonObject.getJSONArray("electricityExpenseManagement").getJSONObject(0).getJSONArray("electricityExpenseBillInfoData").getJSONObject(j).getString("image_path");

                   String partName = jsonObject.getJSONArray("electricityExpenseManagement").getJSONObject(i).getJSONArray("electricityExpenseBillInfoData").getJSONObject(j).getString("image_base64_encode");                

                   FileBody bin = new FileBody(new File(sourceFileUri));

                   reqEntity.addPart(partName, bin);                   
               }
           }

           httppost.setEntity(reqEntity);          
           System.out.println("Requesting : " + httppost.getRequestLine());
           ResponseHandler<String> responseHandler = new BasicResponseHandler();
           responseBody = httpclient.execute(httppost, responseHandler);
           System.out.println("responseBody : " + responseBody);

           return responseBody;

      }
      catch (UnsupportedEncodingException e) {
         e.printStackTrace();
         return e.getMessage(); 
      }
      catch (ClientProtocolException e) {
         e.printStackTrace();
         return e.getMessage(); 
      }
      catch (IOException e) {
         e.printStackTrace();
         return e.getMessage(); 
      }
      catch(Exception e){
         e.printStackTrace();
         System.out.println("error");
         return e.getMessage();     
      }

   }
}

主Android Java文件(定義插件類)

package com.yourpackagename.core;

import android.os.Bundle;
import org.apache.cordova.*;

public class Waterhealth extends DroidGap
{

    private FilesUpload f;

    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        // Set by <content src="index.html" /> in config.xml

        super.init();

        f = new FilesUpload();
        appView.addJavascriptInterface(f, "FilesUpload");


        super.loadUrl(Config.getStartUrl());
        super.loadUrl("file:///android_asset/elect_exp_FS/index.html");
    }
}

用於上傳文件的PHP腳本(Webservice)

<?php

if(isset($_REQUEST['elecExpObj']))
{        
        $obj= json_decode(stripslashes($_REQUEST['elecExpObj']));
        $len = count($obj->electricityExpenseManagement);
        $str = "";
        for($i=0;$i<$len;$i++)
        {
           $bill_count = count($obj->electricityExpenseManagement[$i]->electricityExpenseBillInfoData);
           for($j=0;$j<$bill_count;$j++)
           {
            $filePath = $obj->electricityExpenseManagement[$i]->electricityExpenseBillInfoData[$j]->image_base64_encode;


            if($_FILES[$filePath]['name'])
            {
              if(!$_FILES[$filePath]['error'])
          {
                 $new_file_name = $filePath . rand() . ".jpg"; //rename file    
                 move_uploaded_file($_FILES[$filePath]['tmp_name'], 'uploads/'.$new_file_name);
         $str .= 'Congratulations!  Your file was accepted.';                 
              }
            }
           }
        }
    echo $str;
}
else{
    echo "fail";
}
?>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM