[英]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 ,現在可以正常使用了。 我將繼續討論這個問題,看看是否有人有更好的方法。
與將.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.