觉得博文有用,请点赞,请评论,请关注,谢谢!~
最近项目中实现多图提交,尝试了base64,16进制 异步上传多图。又尝试了一下Android模拟表单提交,
并且把最近学习的TP5用上,写了一个接收多图的接口,测试成功,在这里分享一下。
先上GIF动态图,看个效果,如果符合你的项目或者确定你要了解的内容,再往下看吧:完整项目下载地址:http://download.csdn.net/detail/iwanghang/9792576
首先,在开始动手前,PHP要和Android协商好字段信息。
比如图片image,标题title,内容desc等等等等,协商好了,我们就开工。
PHP:
PHP方面比较简单,先说一下PHP是如何接收的。
http://192.168.1.111/index.php/admin/article/add 这个是我的本地接口
\application\admin\controller\Article.php 这个是接口的文件
以下是接收表单数据、接收表单上传上来的多图的源码:
<?phpnamespace app\admin\controller;
use think\Controller;
class Article extends Controller
{
public function add()
{
if (request()->isPost()) {
$data = [
'title' => input('title'),
'keywords' => input('keywords'),
'desc' => input('desc'),
'cateid' => input('cateid'),
'content' => input('content'),
'time' => time(),
];
// 接收多图
// 获取表单上传文件
$files = request()->file('image');
foreach($files as $file){
// 移动到框架应用根目录/public/uploads/ 目录下
$info = $file->move(ROOT_PATH . 'public' . DS . 'uploads');
if($info){
// 成功上传后 获取上传信息
$data['image'] = 'uploads/'.date('Ymd').'/'.$info->getFilename();
// 输出 jpg
echo "格式:";
echo $info->getExtension();
echo "<br>";
// 输出 42a79759f284b767dfcb2a0197904287.jpg
echo "目录:";
echo $info->getSaveName();
echo "<br>";
}else{
// 上传失败获取错误信息
echo $file->getError();
}
}
return json_encode(\think\Request::instance()->request(false));
return;
}
$cateres = db('cate')->select(); // 查询所有栏目名称
$this->assign('cateres',$cateres); // 分配模板
return $this->fetch();
}
}
Android:
1.首先在Manifest里,申请一堆权限:
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.iwanghang.moreimageupload"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.CAMERA"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.iwanghang.moreimageupload.logic.ImgFileListActivity" android:label="@string/app_name" > </activity> <activity android:name="com.iwanghang.moreimageupload.logic.ImgsActivity" android:label="@string/app_name" > </activity> </application></manifest>
2.我们拆分开多图选择,和多图上传:
2.1.多图选择:
MainActivity.java:
public class MainActivity extends Activity { // 图片选择 ListView listView; ArrayList<String> listfile=new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 图片选择 listView=(ListView) findViewById(R.id.listView1); Bundle bundle= getIntent().getExtras(); if (bundle!=null) { if (bundle.getStringArrayList("files")!=null) { listfile = bundle.getStringArrayList("files"); listView.setVisibility(View.VISIBLE); ArrayAdapter<String> arryAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listfile); listView.setAdapter(arryAdapter); } } } public void chise(View v){ Intent intent = new Intent(); intent.setClass(this,ImgFileListActivity.class); startActivity(intent); }}
logic\FileTraversal.java:
package com.iwanghang.moreimageupload.logic;import java.util.ArrayList;import java.util.List;import android.annotation.SuppressLint;import android.os.Parcel;import android.os.Parcelable;// 文件的类@SuppressLint("ParcelCreator")public class FileTraversal implements Parcelable {public String filename;//所属图片的文件名称public List<String> filecontent=new ArrayList<String>();@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(filename);dest.writeList(filecontent);}public static final Parcelable.Creator<FileTraversal> CREATOR=new Creator<FileTraversal>() {@Overridepublic FileTraversal[] newArray(int size) {return null;}@Overridepublic FileTraversal createFromParcel(Parcel source) {FileTraversal ft=new FileTraversal();ft.filename= source.readString();ft.filecontent= source.readArrayList(FileTraversal.class.getClassLoader());return ft;}};}
logic\ImgCallBack.java:
package com.iwanghang.moreimageupload.logic;import android.graphics.Bitmap;import android.widget.ImageView;public interface ImgCallBack {public void resultImgCall(ImageView imageView, Bitmap bitmap);}
logic\ImgFileListActivity.java:
package com.iwanghang.moreimageupload.logic;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ListView;import com.iwanghang.moreimageupload.R;public class ImgFileListActivity extends Activity implements OnItemClickListener{ListView listView;Util util;ImgFileListAdapter listAdapter;List<FileTraversal> locallist;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.imgfilelist);listView=(ListView) findViewById(R.id.listView1);util=new Util(this);locallist=util.LocalImgFileList();List<HashMap<String, String>> listdata=new ArrayList<HashMap<String,String>>();Bitmap bitmap[] = null;if (locallist!=null) {bitmap=new Bitmap[locallist.size()];for (int i = 0; i < locallist.size(); i++) {HashMap<String, String> map=new HashMap<String, String>();map.put("filecount", locallist.get(i).filecontent.size()+"张");map.put("imgpath", locallist.get(i).filecontent.get(0)==null?null:(locallist.get(i).filecontent.get(0)));map.put("filename", locallist.get(i).filename);listdata.add(map);}}listAdapter=new ImgFileListAdapter(this, listdata);listView.setAdapter(listAdapter);listView.setOnItemClickListener(this);}@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {Intent intent=new Intent(this,ImgsActivity.class);Bundle bundle=new Bundle();bundle.putParcelable("data", locallist.get(arg2));intent.putExtras(bundle);startActivity(intent);}}
logic\ImgFileListAdapter.java:
package com.iwanghang.moreimageupload.logic;import java.io.File;import java.io.FileNotFoundException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import android.content.Context;import android.graphics.Bitmap;import android.net.Uri;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import com.iwanghang.moreimageupload.R;public class ImgFileListAdapter extends BaseAdapter{Context context;String filecount="filecount";String filename="filename";String imgpath="imgpath";List<HashMap<String, String>> listdata;Util util;Bitmap[] bitmaps;private int index=-1;List<View> holderlist;public ImgFileListAdapter(Context context,List<HashMap<String, String>> listdata) {this.context=context;this.listdata=listdata;bitmaps=new Bitmap[listdata.size()];util=new Util(context);holderlist=new ArrayList<View>();}@Overridepublic int getCount() {return listdata.size();}@Overridepublic Object getItem(int arg0) {return listdata.get(arg0);}@Overridepublic long getItemId(int arg0) {return arg0;}@Overridepublic View getView(final int arg0, View arg1, ViewGroup arg2) {Holder holder;if (arg0 != index && arg0 > index) {holder=new Holder();arg1=LayoutInflater.from(context).inflate(R.layout.imgfileadapter, null);holder.photo_imgview=(ImageView) arg1.findViewById(R.id.filephoto_imgview);holder.filecount_textview=(TextView) arg1.findViewById(R.id.filecount_textview);holder.filename_textView=(TextView) arg1.findViewById(R.id.filename_textview);arg1.setTag(holder);holderlist.add(arg1);}else{holder= (Holder)holderlist.get(arg0).getTag();arg1=holderlist.get(arg0);}holder.filename_textView.setText(listdata.get(arg0).get(filename));holder.filecount_textview.setText(listdata.get(arg0).get(filecount));if (bitmaps[arg0] == null) {util.imgExcute(holder.photo_imgview,new ImgCallBack() {@Overridepublic void resultImgCall(ImageView imageView, Bitmap bitmap) {bitmaps[arg0]=bitmap;imageView.setImageBitmap(bitmap);}}, listdata.get(arg0).get(imgpath));}else {holder.photo_imgview.setImageBitmap(bitmaps[arg0]);}return arg1;}class Holder{public ImageView photo_imgview;public TextView filecount_textview;public TextView filename_textView;}}
logic\ImgsActivity.java:
package com.iwanghang.moreimageupload.logic;import java.io.File;import java.io.FileNotFoundException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.net.Uri;import android.os.Bundle;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnTouchListener;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.AdapterView.OnItemSelectedListener;import android.widget.Button;import android.widget.CheckBox;import android.widget.GridView;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.LinearLayout.LayoutParams;import android.widget.RelativeLayout;import com.iwanghang.moreimageupload.MainActivity;import com.iwanghang.moreimageupload.R;public class ImgsActivity extends Activity {Bundle bundle;FileTraversal fileTraversal;GridView imgGridView;ImgsAdapter imgsAdapter;LinearLayout select_layout;Util util;RelativeLayout relativeLayout2;HashMap<Integer, ImageView> hashImage;Button choise_button;ArrayList<String> filelist;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.photogrally);imgGridView=(GridView) findViewById(R.id.gridView1);bundle= getIntent().getExtras();fileTraversal=bundle.getParcelable("data");imgsAdapter=new ImgsAdapter(this, fileTraversal.filecontent,onItemClickClass);imgGridView.setAdapter(imgsAdapter);select_layout=(LinearLayout) findViewById(R.id.selected_image_layout);relativeLayout2=(RelativeLayout) findViewById(R.id.relativeLayout2);choise_button=(Button) findViewById(R.id.button3);hashImage=new HashMap<Integer, ImageView>();filelist=new ArrayList<String>();//imgGridView.setOnItemClickListener(this);util=new Util(this);}class BottomImgIcon implements OnItemClickListener{int index;public BottomImgIcon(int index) {this.index=index;}@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {}}@SuppressLint("NewApi")public ImageView iconImage(String filepath,int index,CheckBox checkBox) throws FileNotFoundException{LinearLayout.LayoutParams params=new LayoutParams(relativeLayout2.getMeasuredHeight()-10, relativeLayout2.getMeasuredHeight()-10);ImageView imageView=new ImageView(this);imageView.setLayoutParams(params);imageView.setBackgroundResource(R.drawable.imgbg);float alpha=100;imageView.setAlpha(alpha);util.imgExcute(imageView, imgCallBack, filepath);imageView.setOnClickListener(new ImgOnclick(filepath,checkBox));return imageView;}ImgCallBack imgCallBack=new ImgCallBack() {@Overridepublic void resultImgCall(ImageView imageView, Bitmap bitmap) {imageView.setImageBitmap(bitmap);}};class ImgOnclick implements OnClickListener{String filepath;CheckBox checkBox;public ImgOnclick(String filepath,CheckBox checkBox) {this.filepath=filepath;this.checkBox=checkBox;}@Overridepublic void onClick(View arg0) {checkBox.setChecked(false);select_layout.removeView(arg0);choise_button.setText("已选择("+select_layout.getChildCount()+")张");filelist.remove(filepath);}}ImgsAdapter.OnItemClickClass onItemClickClass=new ImgsAdapter.OnItemClickClass() {@Overridepublic void OnItemClick(View v, int Position, CheckBox checkBox) {String filapath=fileTraversal.filecontent.get(Position);if (checkBox.isChecked()) {checkBox.setChecked(false);select_layout.removeView(hashImage.get(Position));filelist.remove(filapath);choise_button.setText("已选择("+select_layout.getChildCount()+")张");}else {try {checkBox.setChecked(true);Log.i("img", "img choise position->"+Position);ImageView imageView=iconImage(filapath, Position,checkBox);if (imageView !=null) {hashImage.put(Position, imageView);filelist.add(filapath);Log.i("filapath", "choise filapath->"+filapath);Log.i("filelist", "choise filelist->"+filelist);select_layout.addView(imageView);choise_button.setText("已选择("+select_layout.getChildCount()+")张");}} catch (FileNotFoundException e) {e.printStackTrace();}}}};public void tobreak(View view){finish();}/** * FIXME * 只需要在这个方法把选中的文档目录已list的形式传过去即可 * @param view */public void sendfiles(View view){Intent intent =new Intent(this, MainActivity.class);Bundle bundle=new Bundle();bundle.putStringArrayList("files", filelist);intent.putExtras(bundle);startActivity(intent);}}
logic\ImgsAdapter.java:
package com.iwanghang.moreimageupload.logic;import java.util.ArrayList;import java.util.List;import android.content.Context;import android.graphics.Bitmap;import android.support.v4.util.LruCache;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.CheckBox;import android.widget.CompoundButton;import android.widget.CompoundButton.OnCheckedChangeListener;import android.widget.ImageView;import com.iwanghang.moreimageupload.R;public class ImgsAdapter extends BaseAdapter {Context context;List<String> data;public Bitmap bitmaps[];Util util;OnItemClickClass onItemClickClass;private int index=-1;List<View> holderlist;public ImgsAdapter(Context context,List<String> data,OnItemClickClass onItemClickClass) {this.context=context;this.data=data;this.onItemClickClass=onItemClickClass;bitmaps=new Bitmap[data.size()];util=new Util(context);holderlist=new ArrayList<View>();}@Overridepublic int getCount() {return data.size();}@Overridepublic Object getItem(int arg0) {return data.get(arg0);}@Overridepublic long getItemId(int arg0) {return arg0;}public void setIndex(int index) {this.index = index;}@Overridepublic View getView(int arg0, View arg1, ViewGroup arg2) {Holder holder;if (arg0 != index && arg0 > index) {index=arg0;arg1=LayoutInflater.from(context).inflate(R.layout.imgsitem, null);holder=new Holder();holder.imageView=(ImageView) arg1.findViewById(R.id.imageView1);holder.checkBox=(CheckBox) arg1.findViewById(R.id.checkBox1);arg1.setTag(holder);holderlist.add(arg1);}else {holder= (Holder)holderlist.get(arg0).getTag();arg1=holderlist.get(arg0);}if (bitmaps[arg0] == null) {util.imgExcute(holder.imageView,new ImgClallBackLisner(arg0), data.get(arg0));}else {holder.imageView.setImageBitmap(bitmaps[arg0]);}arg1.setOnClickListener(new OnPhotoClick(arg0, holder.checkBox));return arg1;}class Holder{ImageView imageView;CheckBox checkBox;}public class ImgClallBackLisner implements ImgCallBack{int num;public ImgClallBackLisner(int num) {this.num=num;}@Overridepublic void resultImgCall(ImageView imageView, Bitmap bitmap) {bitmaps[num]=bitmap;imageView.setImageBitmap(bitmap);}}public interface OnItemClickClass{public void OnItemClick(View v, int Position, CheckBox checkBox);}class OnPhotoClick implements OnClickListener{int position;CheckBox checkBox;public OnPhotoClick(int position,CheckBox checkBox) {this.position=position;this.checkBox=checkBox;}@Overridepublic void onClick(View v) {if (data!=null && onItemClickClass!=null ) {onItemClickClass.OnItemClick(v, position, checkBox);}}}}
logic\Util.java:
package com.iwanghang.moreimageupload.logic;import java.io.File;import java.io.FileNotFoundException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Set;import java.util.TreeSet;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.database.Cursor;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.net.Uri;import android.os.AsyncTask;import android.provider.MediaStore;import android.view.Display;import android.widget.ImageView;import android.widget.ListView;import android.widget.SimpleAdapter;public class Util {Context context;public Util(Context context) {this.context=context;}/** * 获取全部图片地址 * @return */public ArrayList<String> listAlldir(){Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);Uri uri = intent.getData();ArrayList<String> list = new ArrayList<String>();String[] proj ={MediaStore.Images.Media.DATA};Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);//managedQuery(uri, proj, null, null, null);while(cursor.moveToNext()){String path =cursor.getString(0);list.add(new File(path).getAbsolutePath());}return list;}public List<FileTraversal> LocalImgFileList(){List<FileTraversal> data=new ArrayList<FileTraversal>();String filename="";List<String> allimglist=listAlldir();List<String> retulist=new ArrayList<String>();if (allimglist!=null) {Set set = new TreeSet();String []str;for (int i = 0; i < allimglist.size(); i++) {retulist.add(getfileinfo(allimglist.get(i)));}for (int i = 0; i < retulist.size(); i++) {set.add(retulist.get(i));}str= (String[]) set.toArray(new String[0]);for (int i = 0; i < str.length; i++) {filename=str[i];FileTraversal ftl= new FileTraversal();ftl.filename=filename;data.add(ftl);}for (int i = 0; i < data.size(); i++) {for (int j = 0; j < allimglist.size(); j++) {if (data.get(i).filename.equals(getfileinfo(allimglist.get(j)))) {data.get(i).filecontent.add(allimglist.get(j));}}}}return data;}// 显示原生图片尺寸大小public Bitmap getPathBitmap(Uri imageFilePath,int dw,int dh)throws FileNotFoundException{//获取屏幕的宽和高/** * 为了计算缩放的比例,我们需要获取整个图片的尺寸,而不是图片 * BitmapFactory.Options类中有一个布尔型变量inJustDecodeBounds,将其设置为true * 这样,我们获取到的就是图片的尺寸,而不用加载图片了。 * 当我们设置这个值的时候,我们接着就可以从BitmapFactory.Options的outWidth和outHeight中获取到值 */BitmapFactory.Options op = new BitmapFactory.Options();op.inJustDecodeBounds = true;//由于使用了MediaStore存储,这里根据URI获取输入流的形式Bitmap pic = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(imageFilePath),null, op);int wRatio = (int) Math.ceil(op.outWidth / (float) dw); //计算宽度比例int hRatio = (int) Math.ceil(op.outHeight / (float) dh); //计算高度比例/** * 接下来,我们就需要判断是否需要缩放以及到底对宽还是高进行缩放。 * 如果高和宽不是全都超出了屏幕,那么无需缩放。 * 如果高和宽都超出了屏幕大小,则如何选择缩放呢》 * 这需要判断wRatio和hRatio的大小 * 大的一个将被缩放,因为缩放大的时,小的应该自动进行同比率缩放。 * 缩放使用的还是inSampleSize变量 */if (wRatio > 1 && hRatio > 1) {if (wRatio > hRatio) {op.inSampleSize = wRatio;} else {op.inSampleSize = hRatio;}}op.inJustDecodeBounds = false; //注意这里,一定要设置为false,因为上面我们将其设置为true来获取图片尺寸了pic = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(imageFilePath), null, op);return pic;}public String getfileinfo(String data){String filename[]= data.split("/");if (filename!=null) {return filename[filename.length-2];}return null;}public void imgExcute(ImageView imageView,ImgCallBack icb, String... params){LoadBitAsynk loadBitAsynk=new LoadBitAsynk(imageView,icb);loadBitAsynk.execute(params);}public class LoadBitAsynk extends AsyncTask<String, Integer, Bitmap>{ImageView imageView;ImgCallBack icb;LoadBitAsynk(ImageView imageView,ImgCallBack icb){this.imageView=imageView;this.icb=icb;}@Overrideprotected Bitmap doInBackground(String... params) {Bitmap bitmap=null;try {if (params!=null) {for (int i = 0; i < params.length; i++) {bitmap=getPathBitmap(Uri.fromFile(new File(params[i])), 200, 200);}}} catch (FileNotFoundException e) {e.printStackTrace();}return bitmap;}@Overrideprotected void onPostExecute(Bitmap result) {super.onPostExecute(result);if (result!=null) {//imageView.setImageBitmap(result);icb.resultImgCall(imageView, result);}}}}
2.2.多图上传:
MainActivity.java:
public class MainActivity extends Activity { // 图片上传 /** * 上传的进度 */ private SeekBar progress; /** * 后台返回的结果 */ private TextView tv_result; private String url = "http://192.168.1.111/index.php/admin/article/add"; private EditText editText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 图片上传 progress = (SeekBar) findViewById(R.id.seekBar1); tv_result = (TextView) findViewById(R.id.textView2); editText = (EditText) findViewById(R.id.editText); // API url findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MultiUpload.IuploadProgress iuploadProgress = new MultiUpload.IuploadProgress() { @Override public void uploadProgress(int progress) { // 进度条显示进度 MainActivity.this.progress.setMax(100); MainActivity.this.progress.setProgress(progress); } @Override public void connectTimeOut() { } @Override public void uploadSuccess(String success) { tv_result.setText(success); } }; List<BasicNameValuePair> texts = new ArrayList<BasicNameValuePair>(); // 随便写了一些键名 键名 添加到数组 texts.add(new BasicNameValuePair("title", "777")); texts.add(new BasicNameValuePair("keywords", "777")); texts.add(new BasicNameValuePair("desc", "777")); texts.add(new BasicNameValuePair("cateid", "777")); texts.add(new BasicNameValuePair("content", "777")); texts.add(new BasicNameValuePair("aaa", "1")); texts.add(new BasicNameValuePair("bbb", "1")); texts.add(new BasicNameValuePair("ccc", "1")); HashMap<File, String> files = new HashMap<File, String>(); // 把内存卡的图片1.jpg 2.jpg 3.jpg 添加到数组 //files.put(new File(Environment.getExternalStorageDirectory(),"1.jpg"), "image[]"); //files.put(new File(Environment.getExternalStorageDirectory(),"2.jpg"), "image[]"); //files.put(new File(Environment.getExternalStorageDirectory(),"3.jpg"), "image[]"); // 把多图选择的图片 添加到数组 Log.e("listfile.size()", String.valueOf(listfile.size())); for (int i=0;i<listfile.size();i++){ File file = new File(listfile.get(i)); files.put(file, "image[]"); } url = editText.getText().toString(); new MultiUpload(url, iuploadProgress).upload(texts, files); } }); }}
MultiUpload.java:
package com.iwanghang.moreimageupload;import android.os.Handler;import android.os.Message;import android.text.TextUtils;import android.util.Log;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.HttpStatus;import org.apache.http.HttpVersion;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.methods.HttpPost;import org.apache.http.conn.ClientConnectionManager;import org.apache.http.entity.mime.MultipartEntityBuilder;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.message.BasicNameValuePair;import org.apache.http.params.CoreConnectionPNames;import org.apache.http.params.CoreProtocolPNames;import org.apache.http.util.EntityUtils;import java.io.File;import java.io.IOException;import java.util.HashMap;import java.util.List;import java.util.Map.Entry;import java.util.Set;/** * 上传表单数据(多文件和多文本) */public class MultiUpload {/** * 请求的服务器地址 */private String url;private Handler handler;private DefaultHttpClient defaultHttpClient;/** * 上传的文本集合........... */private List<BasicNameValuePair> texts;/** * 上传的文件集合.......... */private HashMap<File, String> files;public MultiUpload(String url, final IuploadProgress iuploadProgress) {this.url = url;this.handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case 0:// 上传进度...........iuploadProgress.uploadProgress((Integer) msg.obj);break;case 1:// 连接超时iuploadProgress.connectTimeOut();break;case 2:// 上传成功,看服务返回的结果...........iuploadProgress.uploadSuccess((String) msg.obj);break;default:break;}}};// 死机........if (TextUtils.isEmpty(url)) {throw new IllegalArgumentException("请求的服务器地址为空");}}/** * @param texts * 文本数据集合 * @param files * 文件数据集合 因为上传文件的key有可能相同(name="files[]),所以HashMap<File, String> * * * <form method="post" * action="http://192.168.2.145/wuxifu/test/uploadMulti.php" * enctype="multipart/form-data"> <input type="file" * name="files[]"><br/> * <input type="file" name="files[]"><br/> * <input type="file" name="files[]"><br/> * <input type="text" name="name"></br/> <input type="text" * name="age"></br/> <input type="submit" value="submit"> </form> */public void upload(List<BasicNameValuePair> texts, HashMap<File, String> files) {this.texts = texts;this.files = files;new Thread() {public void run() {iniClient();HttpPost httpPost = iniHttpPost();try {HttpResponse httpResponse = defaultHttpClient.execute(httpPost);if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {// 上传成功closeConnect();//由于我这边服务器编码为gbk,所以编码设置gbk,如果乱码就改为utf-8String result = EntityUtils.toString(httpResponse.getEntity(), "utf-8");Log.e("上传成功........", result);Message msg = handler.obtainMessage(2, result);handler.sendMessage(msg);}} catch (ClientProtocolException e) {// e.printStackTrace();handler.sendEmptyMessage(1);} catch (IOException e) {// e.printStackTrace();handler.sendEmptyMessage(1);}}}.start();}/** * 初始化post的内容 * * @return HttpPost */protected HttpPost iniHttpPost() {HttpPost httpPost = new HttpPost(url);// MultipartEntityBuilderMultipartEntityBuilder create = MultipartEntityBuilder.create();// 普通文本的发送,用户名&密码等if (texts != null && texts.size() > 0) {for (BasicNameValuePair iterable_element : texts) {create.addTextBody(iterable_element.getName(),iterable_element.getValue());Log.i("key",iterable_element.getName());Log.i("value",iterable_element.getValue());}}// 二进制的发送,文件if (files != null && files.size() > 0) {Set<Entry<File, String>> entrySet = files.entrySet();for (Entry<File, String> iterable_element : entrySet) {create.addBinaryBody(iterable_element.getValue(), iterable_element.getKey());//create.addBinaryBody("111", iterable_element.getKey());//create.addBinaryBody("albumFile", iterable_element.getKey(), ContentType.create("image/jpeg"), iterable_element.getValue());Log.i("key", String.valueOf(iterable_element.getKey()));Log.i("value", String.valueOf(iterable_element.getValue()));}}HttpEntity httpEntity = create.build();// 上传内容的长度.............final long contentLength = httpEntity.getContentLength();ProgressOutHttpEntity progressOutHttpEntity = new ProgressOutHttpEntity(httpEntity, new ProgressOutHttpEntity.ProgressListener() {@Overridepublic void transferred(long transferedBytes) {int currentProgress = (int) (100 * transferedBytes / contentLength);// 当前进度.............Message msg = handler.obtainMessage(0, currentProgress);handler.sendMessage(msg);}});// post内容的设置............httpPost.setEntity(progressOutHttpEntity);return httpPost;}/** * 初始化httpClient */private void iniClient() {if (defaultHttpClient == null) {defaultHttpClient = new DefaultHttpClient();// HTTP协议版本1.1defaultHttpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);// 连接超时defaultHttpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);}};/** * 关闭连接 */private void closeConnect(){if(defaultHttpClient!=null){ClientConnectionManager connectionManager = defaultHttpClient.getConnectionManager();if(connectionManager!=null)connectionManager.shutdown();defaultHttpClient=null;}}public interface IuploadProgress {/** * 上传的进度 * * @param progress * (1-100)100就是上传完毕....... */public void uploadProgress(int progress);/** * @param success * 上传成功........... */public void uploadSuccess(String success);/** * 连接超时 */public void connectTimeOut();}}
ProgressOutHttpEntity.java:
package com.iwanghang.moreimageupload;import org.apache.http.HttpEntity;import org.apache.http.entity.HttpEntityWrapper;import java.io.FilterOutputStream;import java.io.IOException;import java.io.OutputStream;/** * ProgressOutHttpEntity:输出流(OutputStream)时记录已发送字节数 */public class ProgressOutHttpEntity extends HttpEntityWrapper {/**进度监听对象**/ private final ProgressListener listener; public ProgressOutHttpEntity(final HttpEntity entity,final ProgressListener listener) { super(entity); this.listener = listener; } @Override public void writeTo(final OutputStream out) throws IOException { this.wrappedEntity.writeTo(out instanceof CountingOutputStream ? out : new CountingOutputStream(out, this.listener)); } /** * 进度监听器接口 */ public interface ProgressListener { public void transferred(long transferedBytes); } /** * @author wuxif_000 内部类........... * */ public static class CountingOutputStream extends FilterOutputStream { private final ProgressListener listener; private long transferred; CountingOutputStream(final OutputStream out, final ProgressListener listener) { super(out); this.listener = listener; this.transferred = 0; } @Override public void write(final byte[] b, final int off, final int len) throws IOException { out.write(b, off, len); this.transferred += len; this.listener.transferred(this.transferred); } @Override public void write(final int b) throws IOException { out.write(b); this.transferred++; this.listener.transferred(this.transferred); } }}
最后,不要忘记jar包:
httpclient-4.2.5.jar
httpcore-4.3.3.jar
httpmime-4.3.6.jar
还有,暴力解决冲突的方法:以下代码加入build.gradle:
packagingOptions { exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/NOTICE' exclude 'META-INF/LICENSE' exclude 'META-INF/LICENSE.txt' exclude 'META-INF/NOTICE.txt' }
补充,Layout忘记贴出来了:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.iwanghang.moreimageupload.MainActivity"> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/button1" > </ListView> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="textPersonName" android:text="http://192.168.1.111/index.php/admin/article/add" android:ems="10" android:textSize="12dp" android:layout_alignParentTop="true" android:id="@+id/editText" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_toRightOf="@+id/textView" android:layout_toEndOf="@+id/textView" /> <TextView android:text="接口地址" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView" android:layout_alignBaseline="@+id/editText" android:layout_alignBottom="@+id/editText" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" android:layout_below="@+id/seekBar1" android:layout_centerHorizontal="true" android:layout_marginTop="40dp" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始上传" android:layout_below="@+id/textView2" android:layout_alignLeft="@+id/button1" android:layout_alignStart="@+id/button1" /> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="hello" android:layout_below="@+id/button2" android:layout_centerHorizontal="true" android:layout_marginTop="18dp" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="选择图片" android:onClick="chise" android:layout_below="@+id/textView1" android:layout_centerHorizontal="true" /> <SeekBar android:id="@+id/seekBar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="26dp" android:layout_below="@+id/editText" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <TextView android:text="图片键名为image[],还有字段title、keywords、desc等" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textView" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:textColor="@color/colorPrimaryDark" android:id="@+id/textView3" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" /></RelativeLayout>imgfileadapter.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ImageView android:id="@+id/filephoto_imgview" android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/imgbg" android:layout_marginLeft="10dp" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="match_parent" android:orientation="vertical" android:layout_marginLeft="10dp" android:gravity="left|center_vertical" > <TextView android:id="@+id/filename_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="文件名称" android:textColor="@android:color/black" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/filecount_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="几张" android:textSize="16dp" android:textColor="#8B7D7B" /> </LinearLayout> </LinearLayout>imgfilelist.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:background="#EFEFEF" > <ListView android:id="@+id/listView1" android:layout_width="fill_parent" android:layout_height="fill_parent" > </ListView></LinearLayout>imgsitem.xml:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" > <ImageView android:id="@+id/imageView1" android:layout_margin="4dp" android:layout_width="wrap_content" android:layout_height="100dp" android:layout_centerInParent="true" android:src="@drawable/imgbg" /> <CheckBox android:id="@+id/checkBox1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@+id/imageView1" android:layout_alignTop="@+id/imageView1" android:checked="false" android:focusable="false" android:clickable="false" /></RelativeLayout>photogrally.xml:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#EFEFEF" > <RelativeLayout android:id="@+id/relativeLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="@android:color/white" > <Button android:id="@+id/button1" android:layout_margin="2dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="返回" android:textColor="@android:color/black" android:background="#ADD8E6" android:onClick="tobreak" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:background="#ADFF2F" android:textColor="@android:color/black" android:layout_margin="2dp" android:onClick="sendfiles" android:text="发送" /> </RelativeLayout> <GridView android:id="@+id/gridView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_below="@+id/relativeLayout1" android:listSelector="@color/bule_overlay" android:numColumns="3" > </GridView> <RelativeLayout android:id="@+id/relativeLayout2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:alpha="0.8" android:background="@android:color/black" > <HorizontalScrollView android:id="@+id/scrollview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_toLeftOf="@+id/button3" android:scrollbars="none" > <LinearLayout android:id="@+id/selected_image_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:orientation="horizontal" > </LinearLayout> </HorizontalScrollView> <Button android:id="@+id/button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:background="#ADD8E6" android:visibility="visible" android:textColor="@android:color/black" android:text="已选择(0)张" /> </RelativeLayout></RelativeLayout>
完整项目下载地址:http://download.csdn.net/detail/iwanghang/9792576
转载请注明出处: http://blog.csdn.net/iwanghang/article/details/65630703
欢迎移动开发爱好者交流
沈阳或周边城市公司有意开发Android,请与我联系
联系方式
微信:iwanghang
QQ:413711276
邮箱:iwanghang@qq.com
觉得博文有用,请点赞,请评论,请关注,谢谢!~