资讯专栏INFORMATION COLUMN

Android 上传图片到服务器 okhttp一

番茄西红柿 / 2622人阅读
 【目录】

 (一)上传图片到服务器一 ---------------------------------Android代码

 (二)上传图片到服务器二---------------------------------Android 系统7.0以上调用相机兼容问题

 (三)上传图片到服务器三 -----------------------------------后台服务器代码

 

一、相关知识

①Android权限申请

②网络访问框架OKHttp

③内存溢出问题:图片压缩

④Android 系统7.0以上调用系统相机无效

⑤有关图片上传过程中遇到的内存溢出问题

 

二、效果展示

 

 

二、代码 ①HTML
 1          
 7                 
12 
13                 
14 
15                 
23 
24 
25             
26      

 

 

②Java代码

<基本功能>

 实体类

 1 public class LoadFileVo {
 2 
 3     File file;
 4 
 5     int pg; //图片下方的进度条
 6 
 7     boolean isUpload = false; //标识该文件是否上传
 8 
 9     Bitmap bitmap;
10 
11     public Bitmap getBitmap() {
12         return bitmap;
13     }
14 
15     public void setBitmap(Bitmap bitmap) {
16         this.bitmap = bitmap;
17     }
18 
19     public boolean isUpload() {
20         return isUpload;
21     }
22 
23     public void setUpload(boolean upload) {
24         isUpload = upload;
25     }
26 
27     public LoadFileVo() {
28     }
29 
30     public LoadFileVo(File file, int pg) {
31         this.file = file;
32         this.pg = pg;
33     }
34 
35     public LoadFileVo(File file, boolean isUpload, int pg,Bitmap bitmap) {
36         this.file = file;
37         this.pg = pg;
38         this.isUpload = isUpload;
39         this.bitmap = bitmap;
40     }
41 
42     public File getFile() {
43         return file;
44     }
45 
46     public void setFile(File file) {
47         this.file = file;
48     }
49 
50     public int getPg() {
51         return pg;
52     }
53 
54     public void setPg(int pg) {
55         this.pg = pg;
56     }
57 }

 

适配器
  1 /*
  2  *Create By 小群子    2018/12/10
  3  */
  4 
  5 public class LoadPicAdapter extends RecyclerView.Adapter {
  6 
  7     Context context;
  8     List fileList = null;
  9     View view;
 10     int picNum = 8;//列表的图片个数最大值
 11 
 12     public LoadPicAdapter(Context context, List fileList) {
 13         this.context = context;
 14         this.fileList = fileList;
 15     }
 16 
 17     public LoadPicAdapter(Context context, List fileList, int picNum) {
 18         this.context = context;
 19         this.fileList = fileList;
 20         this.picNum = picNum;
 21     }
 22 
 23     public interface OnItemClickListener {
 24         void click(View view, int positon);
 25 
 26         void del(View view);
 27     }
 28 
 29     OnItemClickListener listener;
 30 
 31     public void setListener(OnItemClickListener listener) {
 32         this.listener = listener;
 33     }
 34 
 35     @Override
 36     public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 37 
 38         view = LayoutInflater.from(context).inflate(R.layout.load_item_pic, parent, false);
 39         return new MyViewHolder(view);
 40     }
 41 
 42     @Override
 43     public void onBindViewHolder(MyViewHolder holder, final int position) {
 44 
 45         //通过默认设置第一个为空文件为添加退保,且在文件个数小于最大限制值的情况。当图片个数等于最大限制值,第一个则不是添加按钮
 46         if (position == 0&&fileList.get(position).getBitmap()==null) {
 47             holder.ivPic.setImageResource(R.drawable.addpic);//加号图片
 48             holder.ivPic.setOnClickListener(new View.OnClickListener() {
 49                 @Override
 50                 public void onClick(View view) {
 51                     listener.click(view, position);
 52                 }
 53             });
 54             holder.ivDel.setVisibility(View.INVISIBLE);
 55             holder.bg_progressbar.setVisibility(View.GONE);
 56 
 57         } else {
 58 //            Uri uri = Uri.parse(fileList.get(position).getFile().getPath());
 59 //            holder.ivPic.setImageURI(uri);
 60 
 61             holder.ivPic.setImageBitmap(fileList.get(position).getBitmap());
 62             //使用压缩后的图片进行填充到界面上
 63            
64 65 66 holder.ivDel.setVisibility(View.VISIBLE); 67 holder.bg_progressbar.setVisibility(View.VISIBLE); 68 holder.bg_progressbar.setProgress(fileList.get(position).getPg()); 69 } 70 71 72 holder.ivDel.setOnClickListener(new View.OnClickListener() { 73 @Override 74 public void onClick(View view) { 75 //判断图片是否上传,上传后将无法删除 76 if (fileList.get(position).isUpload()) { 77 Toast.makeText(context, "该图片已上传!", Toast.LENGTH_SHORT).show(); 78 } else { 79 fileList.remove(position); 80 if (fileList.size()==picNum-1&&fileList.get(0).getBitmap()!=null){ 81 fileList.add(0,new LoadFileVo()); 82 }//如果数量达到最大数时,前面的加号去掉,然后再减去时,则添加前面的加号 83 notifyDataSetChanged(); 84 if (listener!=null){ 85 listener.del(view);//传递接口,计算图片个数显示在界面中 86 } 87 88 } 89 } 90 }); 91 92 93 } 94 95 @Override 96 public int getItemCount() { 97 return fileList.size(); 98 } 99 100 101 static class MyViewHolder extends RecyclerView.ViewHolder { 102 @BindView(R.id.ivPic) 103 ImageView ivPic; 104 @BindView(R.id.ivDel) 105 ImageView ivDel; 106 @BindView(R.id.bg_progressbar) 107 ProgressBar bg_progressbar; 108 109 View view; 110 111 112 MyViewHolder(View view) { 113 super(view); 114 this.view = view; 115 ButterKnife.bind(this, view); 116 } 117 } 118 }

 

item 布局//布局自行优化
 1 
 6 
 7     
12 
13         
20 
21         
29     
30     
36 
37 

 

 1 List fileList = new ArrayList<>();
 2 LoadPicAdapter adapter = null;
 3 
 4   //这里使用ButterKnife
 5     @BindView(R.id.rvPic)
 6       RecyclerView rvPic;
 7 
 8     @BindView(R.id.tvNum)
 9        TextView tvNum;
10 
11 
12     //初始化Adapter
13     //设置图片选择的接口
14     private void initAdapter() {
15         fileList.add(new LoadFileVo());
16         adapter = new LoadPicAdapter(this, fileList,8);
17         rvPic.setAdapter(adapter);
18         rvPic.setLayoutManager(new GridLayoutManager(this, 3));
19         adapter.setListener(new LoadPicAdapter.OnItemClickListener() {
20             @Override
21             public void click(View view, int positon) {
22                 if (fileList.size()>8){
23                     showShortToast("一次最多上传8张图片!");
24                 }else {
25                     selectPic();  //选择添加图片方法
26                 }
27 
28             }
29 
30             @Override
31             public void del(View view) {
32                 tvNum.setText((fileList.size()-1)+"/8");
33             }
34         });
35     }

 

《核心代码》
 1 String mPhtotPath;
 2 Uri uriImage;
 3 File mPhotoFile = null;
 4 
 5 
 6 //选择图片
 7 private void selectPic() {
 8 
 9 //动态请求权限,除此之外还需进行Androidmanifest.xml中进行请求
10 
11         if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
12                 != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,
13                 Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
14                 || ContextCompat.checkSelfPermission(this,
15                 Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
16             ActivityCompat.requestPermissions(this,
17                     new String[]{Manifest.permission.CAMERA,
18                             Manifest.permission.READ_EXTERNAL_STORAGE,
19                             Manifest.permission.WRITE_EXTERNAL_STORAGE},
20                     1);
21         }
22 
23 
24         final CharSequence[] items = {"相册", "拍照"};
25         AlertDialog.Builder dlg = new AlertDialog.Builder(EndLoadMstActivity.this);
26         dlg.setTitle("添加图片");
27         dlg.setItems(items, new DialogInterface.OnClickListener() {
28             public void onClick(DialogInterface dialog, int item) {
29                 // 这里item是根据选择的方式,
30                 if (item == 0) {
31                     Intent intent = new Intent(Intent.ACTION_PICK);
32                     intent.setType("image/*");
33                     startActivityForResult(intent, 0);
34                 } else {
35                     try {
36                         Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
37                         mPhtotPath = getSDPath() + "/" + getPhotoFileName();
38                         mPhotoFile = new File(mPhtotPath);
39                         if (!mPhotoFile.exists()) {
40                             mPhotoFile.createNewFile();
41                         }
42 //                        uriImage = FileProvider.getUriForFile(EndLoadMstActivity.this, getPackageName() + ".provider", createImageFile());
43 
44                         uriImage = FileProvider.getUriForFile(EndLoadMstActivity.this, "com.ahbcd.app.tms.provider", mPhotoFile);
45                         Log.i("TAG", "onClick: "+mPhtotPath+"---------" + getPackageName() + ".provider");
46                         // uriImage = Uri.fromFile(mPhotoFile);以上一句代替解决相机兼容问题
47                         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
48                         intent.putExtra(MediaStore.EXTRA_OUTPUT, uriImage);
49 
50                         startActivityForResult(intent, 1);
51 
52                     } catch (Exception e) {
53                         e.printStackTrace();
54                     }
55                 }
56             }
57         }).create();
58         dlg.show();
59     }
60 
61 public String getSDPath() {
62         File sdDir = null;
63         boolean sdCardExsit = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
64         if (sdCardExsit) {
65             sdDir = Environment.getExternalStorageDirectory();
66         }
67         return sdDir.toString();
68     }
69 
70     private String getPhotoFileName() {
71         Date date = new Date(System.currentTimeMillis());
72         SimpleDateFormat dateFormat = new SimpleDateFormat("IMG_yyyyMMdd_HHmmss");
73         return dateFormat.format(date) + ".jpg";
74     }

 

注:这里需要在Android中配置一个proveder 具体请参考 Android 系统7.0以上调用相机兼容问题

《获取返回的图片》
 1 //重写onActivityResult方法
 2 @Override
 3     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 4         super.onActivityResult(requestCode, resultCode, data);
 5         if (requestCode == 1) {
 6             BitmapFactory.Options options = new BitmapFactory.Options();
 7             options.inSampleSize = 2; //图片宽高都为原来的二分之一,即图片为原来的四分之一
 8             Bitmap bitmap = BitmapFactory.decodeFile(mPhtotPath, options);
 9             if (bitmap != null) {
10                 if (uriImage != null) {
11                     saveUritoFile(uriImage,1);
12                 }
13 
14                 if (!bitmap.isRecycled()) {
15                     bitmap.recycle(); //回收图片所占的内存
16                     System.gc(); //提醒系统及时回收
17                 }
18             }
19         }
20         if (requestCode == 0) {
21             if (data != null) {
22                 Uri uri = data.getData();
23                 saveUritoFile(uri,0);
24             }
25         }
26 
27     }
28 
29 //将Uri图片类型转换成File,BitMap类型
30 //在界面上显示BitMap图片,以防止内存溢出
31 //上传可选择File文件上传
32 
33     private void saveUritoFile(Uri uriImage,int type) {
34         Bitmap photoBmp = null;
35 
36         if (uriImage != null) {
37             try {
38 //                photoBmp = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uriImage);
39 //                ByteArrayOutputStream fos = new ByteArrayOutputStream();
40 //                photoBmp.compress(Bitmap.CompressFormat.JPEG, 80, fos);
41                 //以上代码压缩不行,还是会造成内存溢出
42 
43                 BitmapFactory.Options options = new BitmapFactory.Options();
44                 options.inSampleSize = 2; //图片宽高都为原来的二分之一,即图片为原来的四分之一
45                 photoBmp = BitmapFactory.decodeStream(this.getContentResolver()
46                         .openInputStream(uriImage), null, options);
47 
48                 File file = new File("");
49                 if (type==0){
50                     file = FileParseUtils.getFileByUri(this, uriImage);
51 
52                 }else {
53                     if (mPhotoFile!=null){
54                         file = mPhotoFile;
55                     }
56 
57                 }
58 //                File file = new File("");
59 //                try {
60 //                    file = new File(new URI(uriImage.toString()));
61 //                } catch (URISyntaxException e) {
62 //                    e.printStackTrace();
63 //                }
64                 fileList.add(new LoadFileVo(file, false, 0, photoBmp));
65                 tvNum.setText((fileList.size()-1)+"/8");
66                 if (fileList.size()>8){    //判断时候达到最大数量,如果达到最大数量,则去掉前面的加号
67                     fileList.remove(0);
68                 }
69 
70                 adapter.notifyDataSetChanged();
71 
72             } catch (IOException e) {
73                 e.printStackTrace();
74                 Log.i("TAG", "saveUritoFile: ---------压缩图片异常!");
75             }
76 
77 
78         }
79 
80     }

 

图片上传到后台OKhttp
  1 //一张张图片轮流上传
  2 public void netUpload(int i, final String joData) {//用jsonOject方式转string传递其他参数
  3         try {
  4 
  5             if (!isRequestHttp) {
  6                 isRequestHttp = true;
  7                 final int finalI = i;
  8                 enterEnable(false);
  9 
 10                 if (fileList.get(finalI).isUpload()) {
 11                     netUpload(finalI + 1, joData);
 12                 } else {
 13 
 14         RequestBody requestBody = new MultipartBody.Builder()
 15                 .setType(MultipartBody.FORM)
 16                 .addFormDataPart("mstjson",msg)  //其他信息
 17                 .addFormDataPart("file", file.getName(),
 18                         RequestBody.create(MediaType.parse("application/octet-stream"), file))//文件
 19                 .build();
 20         Request request = new Request.Builder()
 21                 .url(uploadPic---这里是图片上传的地址).post(requestBody)
 22                 .build();
 23         okHttpClient.newCall(request).enqueue(new UICallBack() {
 24                         @Override
 25                         public void onFailureUI(Call call, IOException e) {
 26                             showShortToast("连接服务器失败");
 27                             isRequestHttp = true;
 28                             enterEnable(true);
 29 
 30                         }
 31 
 32                         @Override
 33                         public void onResponseUI(Call call, Response response) {
 34                             try {
 35 
 36                                 isRequestHttp = false;
 37 
 38                                 String result = response.body().string();
 39                                 Utils.log("上传图片结果:" + result);
 40 
 41 
 42                                 if (!response.isSuccessful()) {
 43                                     Utils.log("响应失败:" + response.code());
 44                                     showShortToast("响应失败:" + response.code());
 45                                     enterEnable(true);
 46 
 47                                     return;
 48                                 }
 49                                 if (result.equals("{}")) {
 50                                     showShortToast("获取服务端数据为空");
 51                                     enterEnable(true);
 52 
 53                                     return;
 54                                 }
 55                                 JSONObject jsonObject = new JSONObject(result);
 56                                 if (jsonObject.getString("IsError").equals("true")) {
 57                                     showShortToast(jsonObject.getString("ErrMsg"));
 58                                     enterEnable(true);
 59 
 60                                 } else {
 61                                     String Data = jsonObject.getString("Data");
 62                                     fileList.get(finalI).setPg(100);
 63                                     fileList.get(finalI).setUpload(true);
 64                                     adapter.notifyDataSetChanged();
 65 
 66                                     if (finalI == fileList.size() - 1) {
 67                                         showShortToast("上传成功!");
 68 
 69                                         btnEnter.setText("已上传");
 70                                        
 71                                     } else {
 72                                         netUpload((finalI + 1), joData);
 73                                     }
 74 
 75                                 }
 76                             } catch (Exception e) {
 77                                 isRequestHttp = true;
 78                                 hideLoadingDialog();
 79                                 showShortToast("上传凭证发生异常!");
 80                                 LogToFile.e("上传凭证发生异常," + e);
 81                                 enterEnable(true);
 82 
 83                             }
 84                         }
 85                     });
 86 
 87        }
 88             }
 89         } catch (Exception e) {
 90             isRequestHttp = true;
 91             hideLoadingDialog();
 92 
 93             showShortToast("上传图片请求异常!");
 94             LogToFile.e("上传图片请求异常," + e);
 95             enterEnable(true);
 96 
 97         }
 98     }
 99 
100 
101 //用来提示用户文件上传的情况。同时也是避免同时反复操作
102 public void enterEnable(boolean isEnabled) {
103         if (isEnabled) {
104             btnEnter.setText("重新上传");
105             btnEnter.setEnabled(true);
106             btnEnter.setBackgroundResource(R.drawable.selecter_button);
107             btnEnter.setTextColor(getResources().getColor(R.color.inButtonText));
108 
109         } else {
110             btnEnter.setText("正在上传···");
111             btnEnter.setEnabled(false);
112             btnEnter.setBackgroundResource(R.drawable.buttonshap);
113             btnEnter.setTextColor(getResources().getColor(R.color.outButtonText));
114         }
115     }

 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/2462.html

相关文章

  • Android常用的网络框架

    摘要:一常用的网络框架大多数应用程序基本都需要连接网络,发送一些数据给服务端,或者从服务端获取一些数据。请求一般采用原生的和的两种网络访问方式。主要是分四个模块数据库模块中的框架,使用了线程池对进行操作。使用无需重写您程序中的网络代码。 一、Android 常用的网络框架大多数应用程序基本都需要连接网络,发送一些数据给服务端,或者从服务端获取一些数据。通常在 Android 中进行网络连接一...

    刘厚水 评论0 收藏0
  • Android网络框架

    摘要:无网读缓存,有网根据过期时间重新请求使用和实现网络缓存。浅析的你了解过吗为什么每次请求都用了长连接完成一次网络请求都经历了什么感兴趣的不妨可以看下。 Android OKHttp3.0 以上使用方法 Android OKHttp3.0 以上使用方法详解 Retrofit 之日志拦截 Retrofit 日志拦截相关介绍 Retrofit源码解析 Retrofit的源码分析将从基本的使用方...

    smallStone 评论0 收藏0
  • Android网络编程6之OkHttp3用法全解析

    摘要:使用前准备配置添加网络权限异步请求惯例,请求百度可以省略,默认是请求请求成功与版本并没有什么不同,比较郁闷的是回调仍然不在线程。 前言 上一篇介绍了OkHttp2.x的用法,这一篇文章我们来对照OkHttp2.x版本来看看,OkHttp3使用起来有那些变化。当然,看这篇文章前建议看一下前一篇文章Android网络编程(五)OkHttp2.x用法全解析。 1.使用前准备 Android ...

    Amos 评论0 收藏0
  • Android OkHttp完全解析 是时候来了解OkHttp

    摘要:一概述最近在群里听到各种讨论的话题,可见的口碑相当好了。不过也说明一个问题,这个执行的线程并不是线程。张鸿洋大家都清楚,的时候,参数是包含在请求体中的所以我们通过。张鸿洋上述代码向服务器传递了一个键值对张鸿洋和一个文件。 一、概述 最近在群里听到各种讨论okhttp的话题,可见okhttp的口碑相当好了。再加上Google貌似在6.0版本里面删除了HttpClient相关API,对于这...

    hedzr 评论0 收藏0
  • 网络相关 - 收藏集 - 掘金

    摘要:关于三请求流程,源码必知掘金前两两片我们介绍了,基本使用和如何查看源码,今天我们正式进入源码分析流程。掘金是一款上的组件。 一篇文章带你走通 OkHttp+Retrofit+Rxjava - Android - 掘金一篇文章带你走通 OkHttp+Retrofit+Rxjava @(Android)[android] ... 升级 Https 的那些事 - Android - 掘金一、...

    haobowd 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<