上传方式为post,上传图片格式为multipart/form-data
自己在做毕设找了很多方法,但是没有找到一个符合我需求的,最后自己汇总了一下大家的方法,集成为我需要的方式
布局文件(自定义的原型头像):
<com.example.ff.bishe2.ui.CircleImageView
android:id="@+id/civ_information"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/ic_mine_head"
android:layout_margin="15dp"/>
Activity(这个activity还有一些其他的功能,所以有一些多余的代码):
public class InformationActivity extends AppCompatActivity implements View.OnClickListener {
private View view;
private TextView tvBack, tvName, tvPhone, tvAddress;
private LinearLayout ll_popup;
private LinearLayout llHead, llName, llPhone, llAddress;
private SharePreferenceUtil sharePreferenceUtil;
private String userid;
//下面这些变量是与题目有关的
private File photoFile; //存放图片文件,最后是上传这个file
private CircleImageView civInformation; //头像控件
private PopUtil pop; //弹出框,选择是从相册选择还是拍照
protected LoadingDialog loadingDialog; //上传如果延迟的话,会显示一个不停转圈的dialog
private PictureCutUtil pictureCutUtil; //图片压缩工具
private String filename = System.currentTimeMillis() + ".png"; //如果拍照的话会存放在一个临时文件,所以文件名也是随时生成,以免混淆
public final static int CONSULT_DOC_PICTURE = 1000; //相册
public final static int CONSULT_DOC_CAMERA = 1001; //拍照
public final static int CONSULT_DOC_CUTTING = 1002; //裁剪
private Uri outputFileUri; //拍照获得的图片的uri
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = getLayoutInflater().inflate(R.layout.activity_information, null);
setContentView(view);
initView();
initPop();
}
//初始化view
private void initView() {
if (loadingDialog == null) {
loadingDialog = new LoadingDialog(this, R.style.DialogTheme);
}
pictureCutUtil = new PictureCutUtil(this);
tvBack = (TextView) findViewById(R.id.tv_information_back);
tvName = (TextView) findViewById(R.id.tv_information_name);
tvPhone = (TextView) findViewById(R.id.tv_information_phone);
tvAddress = (TextView) findViewById(R.id.tv_information_address);
civInformation = (CircleImageView) findViewById(R.id.civ_information);
llHead = (LinearLayout) findViewById(R.id.ll_information_head);
llName = (LinearLayout) findViewById(R.id.ll_information_name);
llPhone = (LinearLayout) findViewById(R.id.ll_information_phone);
llAddress = (LinearLayout) findViewById(R.id.ll_information_address);
tvBack.setOnClickListener(this);
llHead.setOnClickListener(this);
llName.setOnClickListener(this);
llPhone.setOnClickListener(this);
llAddress.setOnClickListener(this);
}
//初始化弹出框
private void initPop() {
pop = new PopUtil(InformationActivity.this, R.layout.item_popupwindows, false);
ll_popup = pop.getLl_popup();
TextView bt1 = (TextView) ll_popup.findViewById(R.id.item_popupwindows_camera);//拍照
TextView bt2 = (TextView) ll_popup.findViewById(R.id.item_popupwindows_Photo);//从相册中选择
TextView bt3 = (TextView) ll_popup.findViewById(R.id.item_popupwindows_cancel);//取消
bt1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
File file = new File(Environment.getExternalStorageDirectory(), filename);
outputFileUri = Uri.fromFile(file);
Intent intentPhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intentPhoto.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intentPhoto, CONSULT_DOC_CAMERA);
overridePendingTransition(R.anim.translate_bottom_in, R.anim.translate_nomal);
pop.dismiss();
ll_popup.clearAnimation();
}
});
bt2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent, "选择图片"), CONSULT_DOC_PICTURE);
overridePendingTransition(R.anim.translate_bottom_in, R.anim.translate_nomal);
pop.dismiss();
ll_popup.clearAnimation();
}
});
bt3.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
pop.dismiss();
}
});
}
@Override
protected void onResume() {
super.onResume();
initData();
}
//做一些数据初始化,与我们讨论的东西无关
private void initData() {
sharePreferenceUtil = new SharePreferenceUtil(this);
civInformation.setImageBitmap(sharePreferenceUtil.getImg(BitmapFactory.decodeResource(getResources(), R.drawable.ic_mine_head)));
tvName.setText(sharePreferenceUtil.getUsername());
tvPhone.setText(sharePreferenceUtil.getPhone());
tvAddress.setText(sharePreferenceUtil.getAddress());
userid = sharePreferenceUtil.getUserID();
}
//在弹出框中选择不同选项,在这里处理返回方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case CONSULT_DOC_PICTURE: //相册选择
uriphoto = data.getData(); //图片已经存在,所以data中就是图片的uri
try {
startPhotoZoom(data.getData()); //头像一般都要裁剪
} catch (Exception e) {
e.printStackTrace();
}
break;
case CONSULT_DOC_CAMERA: //拍照
if (outputFileUri != null) {
startPhotoZoom(outputFileUri); //裁剪
}
break;
case CONSULT_DOC_CUTTING: //裁剪完之后,压缩保存并上传
if (data != null) {
setPicToView(data);
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* 裁剪图片方法实现
* @param uri
*/
public void startPhotoZoom(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
// 设置裁剪
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 320);
intent.putExtra("outputY", 320);
intent.putExtra("return-data", true);
startActivityForResult(intent, CONSULT_DOC_CUTTING); //返回去
}
//裁剪之后的图片不能放回原地址,所以要存放在一个临时file中再上传
private void setPicToView(Intent data) {
Bundle extras = data.getExtras();
if (extras != null) {
// 取得SDCard图片路径做显示
Bitmap photo = extras.getParcelable("data");
sharePreferenceUtil.setImg(photo); //我用sharePreference保存图片
photoFile = pictureCutUtil.cutPictureQuality(photo, "ff"); //压缩并保存
if (loadingDialog != null) { //上传可能要延迟,先弹出等待框
loadingDialog.show();
}
postIcon(); //上传
}
}
//新建子线程上传头像,返回数据提交给handler刷新ui
private void postIcon() {
Thread t = new Thread() {
@Override
public void run() {
String url = "http://119.29.173.118/api/User/SetUserIcon?userid=" + userid;
String response = UploadImage.uploadFile(photoFile, url); //方法后面给出
Message msg = new Message();
msg.obj = response;
msg.what= 1;
handler.sendMessage(msg);
}
};
t.start();
}
// 此方法在主线程中调用,可以更新UI
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
// 处理消息时需要知道是成功的消息还是失败的消息
if (!isFinishing()) loadingDialog.dismiss(); //上传返回后,等待框消失
switch (msg.what) {
case 1:
Toast.makeText(InformationActivity.this, msg.obj.toString() , Toast.LENGTH_LONG).show();
break;
case 0:
Toast.makeText(InformationActivity.this, "请求失败", Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
};
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_information_back:
finish();
break;
case R.id.ll_information_head:
pop.showAtLocation(view, Gravity.BOTTOM, 0, 0);
break;
case R.id.ll_information_name:
IntentUtils.turnTo(InformationActivity.this, NameActivity.class, false);
break;
case R.id.ll_information_phone:
IntentUtils.turnTo(InformationActivity.this, PhoneActivity.class, false);
break;
case R.id.ll_information_address:
IntentUtils.turnTo(InformationActivity.this, AddressActivity.class, false);
break;
}
}
}
PopUtil弹出框:
public class PopUtil extends PopupWindow {
private AutoLinearLayout ll_popup;
private long mLastTime = -1;
private boolean isAnimation;
private Activity activity;
private int layout;
private View bgview;
private View view;
public PopUtil(Activity activity, int layout, boolean isAnimation) {
this.activity = activity;
this.layout = layout;
this.isAnimation = isAnimation;
initPop();
}
public AutoLinearLayout getLl_popup() {
return ll_popup;
}
public View getview() {
return view;
}
public void initPop() {
view = activity.getLayoutInflater().inflate(layout, null);
// pop = new PopupWindow();
ll_popup = (AutoLinearLayout) view.findViewById(R.id.ll_popup);
setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
setBackgroundDrawable(new BitmapDrawable());
setFocusable(true);
setOutsideTouchable(true);
setContentView(view);
// setBackgroundDrawable(new ColorDrawable(activity.getResources().getColor(R.color.black)));
bgview = ll_popup.findViewById(R.id.view);
bgview.setAlpha(0.5f);
// 消失的时候设置窗体背景变亮
// setOnDismissListener(new PopupWindow.OnDismissListener() {
// @Override
// public void onDismiss() {
// }
// });
ll_popup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
// if (isAnimation){
// endAnimationPopup(getAnimation());
// }
}
});
}
public Animation getAnimation() {
final Animation endAnimation = AnimationUtils.loadAnimation(activity, R.anim.translate_bottom_out);
endAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
dismiss();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
return endAnimation;
}
@Override
public void showAtLocation(View parent, int gravity, int x, int y) {
super.showAtLocation(parent, gravity, x, y);
// backgroundAlpha(0.5f);
// bgview.setVisibility(View.VISIBLE);
}
/**
* 防止重复点击关闭pop动画
*
* @param endAnimation
*/
public void endAnimationPopup(Animation endAnimation) {
if (mLastTime == -1) {
ll_popup.startAnimation(endAnimation);
} else {
long currentTimeMillis = System.currentTimeMillis();
long interval = currentTimeMillis - mLastTime;
if (interval < 300) {
return;
} else {
ll_popup.startAnimation(endAnimation);
}
}
mLastTime = System.currentTimeMillis();
}
@Override
public void dismiss() {
super.dismiss();
// backgroundAlpha(1f);
}
/**
* 设置添加屏幕的背景透明度
*
* @param bgAlpha
*/
public void backgroundAlpha(float bgAlpha) {
WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
lp.alpha = bgAlpha; //0.0-1.0
activity.getWindow().setAttributes(lp);
}
}
Pop的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<com.zhy.autolayout.AutoLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_popup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
android:fitsSystemWindows="false"
android:orientation="vertical">
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/black"></View>
<TextView
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/grayEFEFEF" />
<TextView
android:id="@+id/item_popupwindows_camera"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center"
android:padding="20px"
android:text="拍照"
android:textColor="@color/gray585858"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/grayEFEFEF" />
<TextView
android:id="@+id/item_popupwindows_Photo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center"
android:padding="20px"
android:text="从相册中选取"
android:textColor="@color/gray585858"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/grayf3f3f3" />
<TextView
android:id="@+id/item_popupwindows_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center"
android:padding="20px"
android:text="取消"
android:textColor="@color/gray585858"
android:textSize="16sp" />
</com.zhy.autolayout.AutoLinearLayout>
PictureCutUtil图片工具类:
public class PictureCutUtil {
private File temp;
private Context context;
/**
* 构造器
*
* @param context
*/
public PictureCutUtil(Context context) {
this.context = context;
}
/**
* 计算图片的缩放值
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
private int cutBySize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
/**
* 根据路径获得图片并压缩返回bitmap
*
* @param filePath
* @return
*/
public Bitmap cutPictureSize(String filePath) {
Display mDisplay = ((Activity) context).getWindowManager().getDefaultDisplay();
int width = mDisplay.getWidth();
int height = mDisplay.getHeight();
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
options.inSampleSize = cutBySize(options, width, height);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
/**
* 存储图片
*
* @param bitmap
* @param savePackage
* @return
*/
public File cutPictureQuality(Bitmap bitmap, String savePackage) {
String fileName = UUID.randomUUID().toString().replace("-","") + ".png";
String filePath = Environment.getExternalStorageDirectory() + File.separator + savePackage;
// 判断文件夹存在
File file = new File(filePath);
if (file != null && !file.exists()) {
file.mkdirs();
}
try {
// 第一次压缩
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
temp = new File(filePath, fileName);
FileOutputStream fos = new FileOutputStream(temp);
int options = 100;
// 如果大于150kb则再次压缩,最多压缩三次
while (baos.toByteArray().length / 1024 > 150 && options != 10) {
// 清空baos
baos.reset();
// 这里压缩options%,把压缩后的数据存放到baos中
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
options -= 30;
}
fos.write(baos.toByteArray());
fos.close();
baos.close();
} catch (Exception e) {
}
return temp;
}
}
上传头像UploadImage(post方式,multipart/form-data格式):
public class UploadImage {
private static final String TAG = "uploadFile";
private static final int TIME_OUT = 10*10000000; //超时时间
private static final String CHARSET = "utf-8"; //设置编码
private static final String BOUNDARY = "FlPm4LpSXsE" ; //UUID.randomUUID().toString(); //边界标识 随机生成 String PREFIX = "--" , LINE_END = "\r\n";
private static final String PREFIX="--";
private static final String LINE_END="\r\n";
private static final String CONTENT_TYPE = "multipart/form-data"; //内容类型
/** * android上传文件到服务器
* @param file 需要上传的文件
* @param requestURL 请求的rul
* @return 返回响应的内容
*/
public static String uploadFile(File file, String requestURL) {
try {
URL url = new URL(requestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(TIME_OUT);
conn.setConnectTimeout(TIME_OUT);
conn.setDoInput(true); //允许输入流
conn.setDoOutput(true); //允许输出流
conn.setUseCaches(false); //不允许使用缓存
conn.setRequestMethod("POST"); //请求方式
conn.setRequestProperty("Charset", CHARSET);//设置编码
//头信息
conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
if(file!=null) {
/** * 当文件不为空,把文件包装并且上传 */
OutputStream outputSteam=conn.getOutputStream();
DataOutputStream dos = new DataOutputStream(outputSteam);
StringBuffer sb = new StringBuffer();
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINE_END);
sb.append("Content-Disposition: form-data; name=\"file\";filename=" + "\"" + file.getName() + "\"" + LINE_END);
sb.append("Content-Type: image/jpg"+LINE_END);
sb.append(LINE_END);
dos.write(sb.toString().getBytes());
//读取文件的内容
InputStream is = new FileInputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
while((len=is.read(bytes))!=-1)
{
dos.write(bytes, 0, len);
}
is.close();
//写入文件二进制内容
dos.write(LINE_END.getBytes());
//写入end data
byte[] end_data = (PREFIX+BOUNDARY+PREFIX+LINE_END).getBytes();
dos.write(end_data);
dos.flush();
/**
* 获取响应码 200=成功
* 当响应成功,获取响应的流
*/
int res = conn.getResponseCode();
if(res==200) {
String oneLine;
StringBuffer response = new StringBuffer();
BufferedReader input = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((oneLine = input.readLine()) != null) {
response.append(oneLine);
}
return response.toString();
}else{
return ""+res;
}
}else{
return "file not found";
}
} catch (MalformedURLException e) {
e.printStackTrace();
return "Malformed failed";
} catch (IOException e) {
e.printStackTrace();
return "IO failed";
}
}
}
效果图: