zoukankan      html  css  js  c++  java
  • Android 上传图片到服务器 okhttp一

     【目录】

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

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

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

     

    一、相关知识

    ①Android权限申请

    ②网络访问框架OKHttp

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

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

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

     

    二、效果展示

     

     

    二、代码

    ①HTML

     1          <LinearLayout
     2                 android:layout_width="match_parent"
     3                 android:layout_height="wrap_content"
     4                 android:orientation="vertical"
     5                 android:background="@color/white"
     6                 >
     7                 <android.support.v7.widget.RecyclerView
     8                     android:id="@+id/rvPic"
     9                     android:layout_width="wrap_content"
    10                     android:layout_height="match_parent"
    11                     android:layout_gravity="center_horizontal">
    12 
    13                 </android.support.v7.widget.RecyclerView>
    14 
    15                 <TextView
    16                     android:id="@+id/tvNum"
    17                     android:layout_width="wrap_content"
    18                     android:layout_height="wrap_content"
    19                     android:text="0/8"
    20                     android:textColor="#666666"
    21                     android:layout_gravity="right|bottom"
    22                     android:paddingRight="@dimen/dp_10"/>
    23 
    24 
    25             </LinearLayout>
    26      <Button
    27 
    28         android:id="@+id/btn_Enter"
    29         android:layout_width="match_parent"
    30         android:layout_height="@dimen/dp_45"
    31         android:layout_alignParentBottom="true"
    32         android:background="@drawable/selecter_button"
    33         android:text="确认上传"
    34         android:textColor="@color/inButtonText"
    35         android:textSize="@dimen/dp_18" />

     

     

    ②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<LoadPicAdapter.MyViewHolder> {
      6 
      7     Context context;
      8     List<LoadFileVo> fileList = null;
      9     View view;
     10     int picNum = 8;//列表的图片个数最大值
     11 
     12     public LoadPicAdapter(Context context, List<LoadFileVo> fileList) {
     13         this.context = context;
     14         this.fileList = fileList;
     15     }
     16 
     17     public LoadPicAdapter(Context context, List<LoadFileVo> 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 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     android:layout_width="@dimen/dp_110"
     3     android:layout_height="@dimen/dp_115"
     4 
     5     >
     6 
     7     <LinearLayout
     8         android:layout_width="match_parent"
     9         android:layout_height="match_parent"
    10         android:orientation="vertical"
    11         android:padding="@dimen/dp_5">
    12 
    13         <ImageView
    14             android:id="@+id/ivPic"
    15             android:layout_width="match_parent"
    16             android:layout_height="@dimen/dp_100"
    17             android:scaleType="centerCrop"
    18             android:src="@drawable/ic_pick"
    19             />
    20 
    21         <ProgressBar
    22             android:id="@+id/bg_progressbar"
    23             style="@style/StyleProgressBarMini"
    24             android:layout_width="match_parent"
    25             android:layout_height="@dimen/dp_5"
    26             android:background="@drawable/shape_progressbar_mini"
    27             android:max="100"
    28             android:progress="60" />
    29     </LinearLayout>
    30     <ImageView
    31         android:id="@+id/ivDel"
    32         android:layout_width="@dimen/dp_25"
    33         android:layout_height="@dimen/dp_25"
    34         android:src="@drawable/delete_round"
    35         android:layout_alignParentRight="true"/>
    36 
    37 </RelativeLayout>

     

     1 List<LoadFileVo> 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     }

     

  • 相关阅读:
    zipfile和tarfile的简单使用方法
    RabbitMQ安装
    postman接口自动化
    linux命令
    redis安装部署和使用
    nmon使用
    jdk自带监控工具配置使用
    修改本机mac
    hashlib模块,md5加密
    tomcat部署
  • 原文地址:https://www.cnblogs.com/xqz0618/p/uploadPic01.html
Copyright © 2011-2022 走看看