Android|Android上传头像或上传文件之Retrofit2 使用@Multipart使用标签@PartMap

前言 早上到下午搞了一天的bug
因为突然停电,导致android studio 不能正常运行 所有的项目都不能运行
xml乱码 项目乱码 R文件丢失 等问题!
心态极度崩溃 最后功夫不负有心人 还好解决了

以上文字和博文没有任何牵连 只是被bug搞的很崩溃
再次记录一下

进入正题 后台希望我们传一个file格式的图片 上传到服务器
然后返回一个服务器保存的图片地址 类似这样的格式
/static/images/upload/20200818/ccf0fca9f8c37bed259e0d71707c005c.jpg
最后我们请求接口获取到这个地址 加上服务器域名即可显示这个图片

看下实现效果
请求格式 使用Retrofit2

@Multipart @POST(HttpService.UPLOAD_AVATAR) Observable> uploadAvatar(@PartMap Map files, @Part MultipartBody.Part file);

Presenter层代码逻辑实现
  • 1.先实现对参数的封装
//创建 RequestBody,用于封装构建RequestBody private RequestBody toRequestBody(String value) { RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), value); return requestBody; }

  • 2.再操作接口
/** * 上传头像 * * @param path */ @Override public void uploadAvatar(String path) { //文件格式 File file = new File(path); // 创建 RequestBody,用于封装构建RequestBody RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file); //和后端约定好Key,这里的partName是用file MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile); if (UserUtils.getUserInfo() == null) return; String userId = UserUtils.getUserInfo().getId() + ""; String token = StringUtils.getToken(); Map params = new HashMap<>(); params.put("user_id", toRequestBody(userId)); params.put("appid", toRequestBody(APP_ID)); params.put("token", toRequestBody(token)); mCompositeDisposable.add(mFullOilApi.uploadAvatar(params, body) .subscribeOn(Schedulers.io()) .doOnSubscribe(new Consumer() { @Override public void accept(Disposable disposable) throws Exception { mCompositeDisposable.add(disposable); mPersonalInfoView.requestStart(); } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer>() { @Override public void accept(BaseBean baseBean) throws Exception { mPersonalInfoView.requestComplete(); if (baseBean.getCode() == SUCCESS) { if (UserUtils.getAppConfig() != null) { String apiUrl = UserUtils.getAppConfig().getApp_url(); //按照后台要求拼接图片地址 String imaUrl = apiUrl + "/static/images/upload/" + baseBean.getData().get(0).getSaveName(); mPersonalInfoView.changeUserAvatar(imaUrl); } } else { mPersonalInfoView.showErrorMessage(baseBean.getMessage()); } } }, new Consumer() { @Override public void accept(Throwable throwable) throws Exception { mPersonalInfoView.showErrorMessage(HttpUtils.getHttpErrorMessage(mContext, throwable)); mPersonalInfoView.requestComplete(); } })); }

总结 如此头像上传就完成了 不过上传头像之前需要裁切
我是找的第三方组件

//裁剪图片 implementation 'com.github.yalantis:ucrop:2.2.1'

代码实现在这里也贴出来共享一下
//头像裁减 public class CropActivity extends AppCompatActivity {public static final String EXTRA_PATH = "extra_path"; public static final int REQUEST_CODE = 33; private Unbinder mUnbinder; @BindView(R.id.toolbar) Toolbar mToolbar; @BindView(R.id.ucropview) UCropView mUCropView; private GestureCropImageView mCropImage; private OverlayView mOverlayView; private String mOutputPath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_crop); StatusBarUtils.transparencyBar(this); mUnbinder = ButterKnife.bind(this); setSupportActionBar(mToolbar); getSupportActionBar().setDisplayShowTitleEnabled(false); mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); mCropImage = mUCropView.getCropImageView(); mOverlayView = mUCropView.getOverlayView(); mCropImage.setTransformImageListener(mCropListener); mCropImage.setRotateEnabled(false); mOverlayView.setShowCropGrid(false); String cacheDir = FileUtils.getAppPath(); File file = new File(cacheDir, "ucrop_user_avatar.jpg"); mOutputPath = file.getAbsolutePath(); Uri destinationUri = Uri.fromFile(file); String path = getIntent().getStringExtra(EXTRA_PATH); try { mCropImage.setImageUri(Uri.parse(path), destinationUri); } catch (Exception e) { e.printStackTrace(); } }@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_confirm, menu); return super.onCreateOptionsMenu(menu); }@Override public boolean onOptionsItemSelected(MenuItem item) { mCropImage.cropAndSaveImage(Bitmap.CompressFormat.JPEG, 70, new BitmapCropCallback() { @Override public void onBitmapCropped(@NonNull Uri resultUri, int offsetX, int offsetY, int imageWidth, int imageHeight) { Log.e("CropActivity", "裁剪图片成功" + resultUri); File file = new File(mOutputPath); if (file.exists()) { Log.e("CropActivity", "图片大小" + file.getTotalSpace()); } Intent intent = new Intent(); intent.putExtra(EXTRA_PATH, mOutputPath); setResult(RESULT_OK, intent); finish(); }@Override public void onCropFailure(@NonNull Throwable t) { Log.e("CropActivity", "裁剪图片失败"); } }); return true; }private TransformImageView.TransformImageListener mCropListener = new TransformImageView.TransformImageListener() { @Override public void onRotate(float currentAngle) { }@Override public void onScale(float currentScale) { }@Override public void onLoadComplete() { mCropImage.setTargetAspectRatio(1); mCropImage.postTranslate(1, 1); }@Override public void onLoadFailure(@NonNull Exception e) { }}; @Override protected void onDestroy() { super.onDestroy(); mUnbinder.unbind(); } }

共勉
【Android|Android上传头像或上传文件之Retrofit2 使用@Multipart使用标签@PartMap】我要一步一步往上爬
在最高点乘着叶片往前飞
任风吹干流过的泪和汗
我要一步一步往上爬
等待阳光静静看着它的脸
小小的天有大大的梦想
我有属于我的天
任风吹干流过的泪和汗
总有一天我有属于我的天
Android|Android上传头像或上传文件之Retrofit2 使用@Multipart使用标签@PartMap
文章图片

    推荐阅读