推广

超级完整版android 图片上传,包括客户端和后台服务器

iseeyu3年前 (2024-02-22)推广137

第一个是图片选择框架

第二个是图片加载工具

需要引用jitpack的库

具体使用我就不多讲了,gIthub地址—>https://github.com/LuckSiege/PictureSelector

需要注意的是要用到gitbub  demo包里的一个工具类

所以建议你把demo项目下载,里面的具体调用方法和注释写的很详细

但我们不要繁杂的写在一个Activity里,所以我们自己封装,上代码

这是调用相册的方法,具体其他api可以自己依照我的方法往下加方法即可

package com.xqb.photography_app.tool;

import android.app.Activity;

import android.util.Log;

import androidx.core.content.ContextCompat;

import com.luck.picture.lib.PictureSelector;

import com.luck.picture.lib.config.PictureConfig;

import com.luck.picture.lib.config.PictureMimeType;

import com.luck.picture.lib.entity.LocalMedia;

import com.luck.picture.lib.listener.OnResultCallbackListener;

import com.luck.picture.lib.style.PictureWindowAnimationStyle;

import com.xqb.photography_app.R;

import java.util.List;

/*

*create by xqb on 2020/9/8

*/

public class MyPictureSelector{

private static MyPictureSelectormyPictureSelector;

    private MyPictureSelector() {

}

//实现单例

    public static MyPictureSelectorgetInstance() {

if (myPictureSelector ==null) {

synchronized (MyPictureSelector.class) {

if (myPictureSelector ==null) {

return myPictureSelector =new MyPictureSelector();

                }

}

}

return myPictureSelector;

    }

//启动推出动画,demo包里也有具体说明

    private PictureWindowAnimationStylepictureWindowAnimationStyle;

    //具体调用方法

    public void openAlbum(Activity activity,int maxSelectNum,boolean isOneSelect,boolean isCrop,boolean isCircleCrop,boolean isCropBorder,final OnSelectorResult onSelectorResult){

pictureWindowAnimationStyle =new PictureWindowAnimationStyle();

        pictureWindowAnimationStyle.ofAllAnimation(R.anim.picture_anim_up_in, R.anim.picture_anim_down_out);

        int selectionMode;

        if (isOneSelect){

selectionMode=PictureConfig.SINGLE;

        }else{

selectionMode=PictureConfig.MULTIPLE;

        }

PictureSelector.create(activity)

.openGallery(PictureMimeType.ofImage())

.imageEngine(GlideEngine.createGlideEngine())//这是需要用到demo包里的一个工具类

                .theme(R.style.picture_white_style)//style配置demo包里也有

                .maxSelectNum(maxSelectNum)

.selectionMode(selectionMode)//单选 PictureConfig.SINGLE

                .isSingleDirectReturn(true)// 单选模式下是否直接返回,PictureConfig.SINGLE模式下有效

                .isCamera(false)//是否使用相机

                .setPictureWindowAnimationStyle(pictureWindowAnimationStyle)// 自定义相册启动退出动画

                .circleDimmedLayer(isCircleCrop)// 是否圆形裁剪

                .isEnableCrop(isCrop)// 是否裁剪

                .showCropFrame(isCropBorder)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false

                .isCompress(true)// 是否压缩

                .compressQuality(100)// 图片压缩后输出质量 0~ 100

                .synOrAsy(false)//同步true或异步false 压缩 默认同步

//                        .compressSavePath(getPath())//压缩图片保存地址

                .setCropDimmedColor(ContextCompat.getColor(activity, R.color.black80Color))// 设置裁剪背景色值

                .withAspectRatio(1, 1)// 裁剪比例 如16:9 3:2 3:4 1:1 可自定义

//                .renameCompressFile(“icon-” + PrefTool.getString(activity, “userPhone”, “”) + “.jpg”)// 重命名压缩文件名、 如果是多张压缩则内部会自动拼上当前时间戳防止重复

                .forResult(new MyResultCallback(onSelectorResult));//自定义回调接口

    }

//因为这里把调用方法写出来了,所以在activity里的OnActivityResult方法里是监听不到的

//这是后需要自己实现回调接口

    public interface OnSelectorResult{

void onResult(List result);

    }

//这是demo里自定义的回调类,我稍作了修改,让它变成具体调用方法的实现回调监听接口

    private static class MyResultCallbackimplements OnResultCallbackListener{

private OnSelectorResultonSelectorResult;

        public MyResultCallback(OnSelectorResult onSelectorResult) {

super();

            this.onSelectorResult=onSelectorResult;

        }

@Override

        public void onResult(List result) {

onSelectorResult.onResult(result);

        }

@Override

        public void onCancel() {

Log.d(“—–>图片选择”, “onCancel: 退出了”);

        }

}

}

调用方法

比起demo里的调用方法整洁了不少,看着舒服,尤其是哪个回调接口的实现,我瞬间有自豪的感觉了,哈哈哈哈

result里就是装的图片信息了,如何获取,demo包里也写的清楚,具体我不多说了

最重要的一部要来了,如何上传,因为图片可选一张可选多张,还需携带用户字符信息,上代码

这里的okhttp也是封装了的,带我的大佬写的,感觉还蛮实用,我在他的基础上改成了图片上传请求

public void doGetForPic(String url,JSONObject object, final OkCallback okCallback) {

Log.i(“TAG”, “” + object.toString());

        final MultipartBody.Builder builder =new MultipartBody.Builder();

        try {

builder.addFormDataPart(“data”,object.getString(“data”));

            JSONArray array=object.getJSONArray(“pic”);

            for (int i=0;i

JSONObject object1=array.getJSONObject(i);

                //文件路径中文转码,否者会报错

//                StringBuffer stringBuffer = new StringBuffer();

//                for (int j = 0, length = object1.getString(“picPath”).length(); j < length; j++) {

//                    char c = object1.getString(“picPath”).charAt(i);

//                    if (c <= ‘\u001f’ || c >= ‘\u007f’) {

//                        stringBuffer.append(String.format(“\\u%04x”, (int) c));

//                    } else {

//                        stringBuffer.append(c);

//                    }

//                }

                builder.addFormDataPart(“img[]”,object1.getString(“picName”), RequestBody.create(MediaType.parse(“image/jpeg”), new File(object1.getString(“picPath”))));

            }

}catch (JSONException e) {

e.printStackTrace();

            Log.e(“——>图片上传异常”,e+””);

        }

RequestBody requestBody = builder.build();

        Request.Builder reqBuilder =new Request.Builder();

        Request request =reqBuilder

.post(requestBody)

.url(url)

.build();

        final Call call =mOkHttpClien.newCall(request);

        call.enqueue(new Callback() {

@Override

            public void onFailure(Call call, final IOException e) {

if (okCallback !=null) {

//切换到主线程

                    mHandler.post(new Runnable() {

@Override

                        public void run() {

okCallback.onFailure(e);

                        }

});

                }

}

@Override

            public void onResponse(Call call, final Response response)throws IOException {

try {

if (response !=null && response.isSuccessful()) {

final String json = response.body().string();

                        if (okCallback !=null) {

Log.i(TAG, “onResponse: ” + Thread.currentThread().getName());

                            mHandler.post(new Runnable() {

@Override

                                public void run() {

Log.i(TAG, “onResponse: ” + Thread.currentThread().getName());

                                    okCallback.onResponse(json);

                                }

});

return;

                        }

}

}catch (IOException e) {

e.printStackTrace();

                }

if (okCallback !=null) {

mHandler.post(new Runnable() {

@Override

                        public void run() {

okCallback.onFailure(new Exception(“请求失败”));

                        }

});

                }

}

});

    }

是不是有点看不懂,其实很好理解,除了上传的参数解析外,其余的操作就是让请求跑在子线程上,请求完成让它回到当前主UI线程

请求调用

private void uploadUserIcon(List result) {

JSONObject object =new JSONObject();

    JSONArray array =new JSONArray();

    try {

for (LocalMedia media : result) {

JSONObject object1 =new JSONObject();

            object1.put(“picName”, media.getFileName()).put(“picPath”, media.getCompressPath());

            array.put(object1);

        }

object.put(“pic”, array);

        object.put(“data”, new JSONObject()

.put(“userPhone”, PrefTool.getString(context, “userPhone”, “”))

.put(“picType”, “icon”)

.put(“userId”, PrefTool.getInt(context, “userId”, 0)));

    }catch (Exception e) {

e.printStackTrace();

    }

OkhttpUtil.getInstance().doGetForPic(IP.requestPicUrl, object, new OkhttpUtil.OkCallback() {

@Override

        public void onFailure(Exception e) {

e.printStackTrace();

            MyToast.toast(context, ToastTextHelper.okhttpOnFailText);

        }

@Override

        public void onResponse(String json) {

try {

Log.e(TAG, “onResponse: ” + json);

                JSONObject responseJson =new JSONObject(json);

                if (responseJson.getBoolean(“status”)) {

PrefTool.setString(context, “userIcon”,responseJson.getString(“data”));

                    Picasso.get().load(IP.requestImgUrl + PrefTool.getString(context, “userIcon”, “”)).transform(new CircleTransform()).into(myInfoIcon);

                }else {

MyToast.toast(context, responseJson.getString(“message”));

                }

}catch (JSONException e) {

e.printStackTrace();

                Log.e(TAG, ToastTextHelper.okhttpOnResponseErrText);

            }

}

});

}

后台服务器解析

添加依赖包

然后以下这是写在service层具体实现的代码

@Override

public MapuploadUserIcon(HttpServletRequest request) {

MultipartRequest multipartRequest = (MultipartRequest) request;

    List list = multipartRequest.getFiles(“img[]”);

    JSONObject requestJson =new JSONObject(request.getParameter(“data”));

    System.out.println(“图片参数”+requestJson);

    switch (requestJson.getString(“picType”)) {

case “icon”:

MultipartFile file = list.get(0);

            if (file ==null || file.getSize() ==0) {

map.put(“status”,false);

                map.put(“message”,”文件损坏”);

            }else{

String fileName=”icon-“+requestJson.getString(“userPhone”)+”.jpg”;

                String filePath=iconSavePath+fileName;

                try {

file.transferTo(new File(filePath));

                    UserTb userId=new UserTb();

                    userId.setUserId(requestJson.getInt(“userId”));

                    userId.setUserIcon(“/myInfoImg/”+fileName);

                    int update =userTbMapper.updateByPrimaryKeySelective(userId);

                    if (update>0){

userTb=userTbMapper.selectByPrimaryKey(requestJson.getInt(“userId”));

                        map.put(“status”,true);

                        map.put(“message”,”图片上传成功”);

                        map.put(“data”,userTb.getUserIcon());

                    }else{

map.put(“status”,false);

                        map.put(“message”,”图片上传失败”);

                    }

}catch (IOException e) {

e.printStackTrace();

                    map.put(“status”,false);

                    map.put(“message”,”图片上传失败”);

                }

}

break;

        case “photo”:

break;

    }

return map;

}

基本上就完成了,我因为之前写过一个类似的版本,写起现在这个来就很容易了,所以没有写很多注释,但是代码并不难,所以仔细看,不懂的可以再找我要demo,到时候要的多,我写个demo放github,到此结束

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/55820.html

相关文章

西安企业做百度推广,一个月花三千和花三万到底差在哪?

4|最近跟几个西安的老板聊天,发现一个挺有意思的现象:同样做百度推广,有人一个月花三千块,询盘不断;有人一个月砸三万,水花都没见着。问他们区别在哪,大多数人说不清楚,只知道'钱花了,没效果'。 5| 6|百度推广这东西,说复杂也复杂,说简单也简单。核心就一件事:让你的潜在客户搜某个词的时候,你的信息...

我想当策划,大学应该选什么专业?

我想当策划,大学应该选什么专业?

学,广告,传播,公关,这些专业其实都可以。另外也可以学像汉语言文学,以及一些跟文学相关的一些专业,会对你找工作有帮助。但是,你想从事这个这份职业,除了专业的学习之外,更多的是,你要在上学的时候积极参与一些更营销策划相关的社会实践。比如说你可以做一些兼职,比如说帮别人去写稿,...

服装市场营销策略分析,“定位不慎满盘皆输”

服装市场营销策略分析,“定位不慎满盘皆输”

不同的区域需要不同的策略,而不同的营销策略需要不同的销售思路来配合。因此,在研究女装产品销售思路之前,最好先对于市场与营销策略做一次深入地了解。1.市场区域化(market segmentation):目标营销的第一步,是将整个市场拆分成若干个同性质的小市场。2.目标市场的...

晚间悦读丨你的思维方式,决定你的人生高度!

晚间悦读丨你的思维方式,决定你的人生高度!

越长大,越发现,能够决定你人生高度的,往往是你的认知层次。 你的认知在哪个层级,你的人生就处在什么状态。你认知的高度,决定了你人生的高度。 那如何才能升级方式、提升认知能力呢?可以从这三个方面做出改变。 NO. 1 改变态度 有人...

编写项目营销策划方案六大要点

编写项目营销策划方案六大要点

现在商业发展非常迅速,的需求非常的大,但是要做好营销策划是有一定难度的,我把自己做营销策划的一些体会在这里分享给朋友们。营销策划方案六大要点我们先说项目营销策划方案这个话题。大部分的营销策划人都是在企业里工作,大部分项目之初都是来源于一个想法,创始人、老板或者创始团队的一个...

【商场营销策划】如何进行商场营销策划?

【商场营销策划】如何进行商场营销策划?

商场是策划者们关注的永恒话题,那么究竟该如何作好商场营销策划呢?掌握以下这几点营销策略设计原则,至关重要!1.义利兼顾的原则。商场在获取利润的同时要充分考虑到消费者的合法利益和商场的长远利益。在作商场活动营销策略方案的时候应该将这一点作为首要的原则。对商场有利而对顾客不利的...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片