Android 通过图库或相机加载图片,并将图片传到服务器上

语言: CN / TW / HK

–添加权限

    <uses permissionandroid:name="com.android.launcher.permission.READ_SETTINGS" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" /> 

–使用相机获得图片
–1

  private  Uri ImageUri=null;

   		创建一个File对象,用于储存拍照后的图片,并把图片命名为outputImage.jpg,
   		并把它手机Sd卡的应用缓存的位置(就是指Sd卡中专门用于存放当前应用缓存数据
   		的位置,调用getExternalCacheDir()方法可以得到这个目录。)
   		如果我们使用这种应用缓存目录来存放图片,就可以跳过运行时权限的处理,
   		(Android6.系统开始,读写Sd卡被列为了危险权限,需要进行运行时权限的处理)。
   		
		 File outputImage=new File(getExternalCacheDir(),"outputImage.jpg");
        try {
   
   
            if (outputImage.exists()){
   
   
                outputImage.delete();
            }
            outputImage.createNewFile();
        } catch (IOException e) {
   
   
            e.printStackTrace();
        }
        这里进行了一个判断,如果运行设备版型低于Android7.0,就调用Uri的formFile()方法。
        否则,就调用FileProvider的getUriForFile()方法将File对象转为一个封装过的Uri。
        if (Build.VERSION.SDK_INT>=24){
   
   
            ImageUri= FileProvider.getUriForFile(CallThePolice.this,
                    "com.example.car.fileprovider",outputImage);
        }else {
   
   
            ImageUri=Uri.fromFile(outputImage);
        }
        //启动相机程序
        Intent intent=new Intent("android.media.action.IMAGE_CAPTURE");
        intent.putExtra(MediaStore.EXTRA_OUTPUT,ImageUri);
        startActivityForResult(intent,2);
 

–2
在AndroidManifest.xml中内容提供器进行注册。

   <provider
            android:authorities="com.example.car.fileprovider"
            android:name="android.support.v4.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>
        </provider>
其中android:authorities 属性必须要和刚才FileProvider,getUriForFile()方法的第二个参数一致。另外,
这里还在<provider>标签的内部使用<meta-data>来指定Uri的共享路径,引用一个@xml/file_paths资源。

–3
在res的xml目录下创建file_path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path  name="camera_photos"  path="" />
</paths>

其中,external-path就是用来指定Uri共享的,name属性可以随便改,path属性的值表示共享的具体路径,这里设空表示将整个卡进行共享。

最后,为了兼容Android4.4以下的老版本,在AndroidManifest.xml下声明,访问Sd卡的权限。

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

–2调用图库获得图片

  Intent intent = new Intent();
  intent.setType("image/*");//选图片
  intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);//选择多张图片
  intent.setAction(Intent.ACTION_GET_CONTENT);
   //Intent.createChooser(),创建应用选择器,系统会根据条件进行过滤            
  startActivityForResult(Intent.createChooser(intent, "select_picture"), 1);

–3处理相机和图库中来的图片

–1首先创建一个RecyclerView的Adapter

public class PictureAdapter extends RecyclerView.Adapter<PictureAdapter.MyViewHolder> {
   
   

    private Context mContext;
    private List<Bitmap> mDatas;
    private LayoutInflater mInflater;
    public PictureAdapter(Context context, List<Bitmap> datas, ) {
   
   
        mContext = context;
        mDatas   = datas;
        mInflater = LayoutInflater.from(context);
    }
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
   
   
        View itemView = mInflater.inflate(R.layout.load_item_pic, parent, false);
        final MyViewHolder holder=new MyViewHolder(itemView);

        return holder;
    }
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
   
    
            Bitmap bitmap= mDatas.get(position);
            holder.mIvDisPlayItemPhoto.setImageBitmap(bitmap);
    }

    @Override
    public int getItemCount() {
   
   
        return mDatas.size();
    }
    public class MyViewHolder extends RecyclerView.ViewHolder {
   
   
        @Bind(R.id.ivPic)
        ImageView mIvDisPlayItemPhoto=itemView.findViewById(R.id.ivPic);
        public MyViewHolder(View itemView) {
   
   
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }
 }

–2在onActivityResult中处理相机和图库中来的数据

private  List<Bitmap> bitmap = new ArrayList<>();//用来储存拍照和图库中来的图片
private  List<Uri> URI = new ArrayList<>();//用来记录要上传照片的路径,上传到服务器要用到
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
   
   
        super.onActivityResult(requestCode, resultCode, data);
        int i = 0;
        recyclerView = findViewById(R.id.picture);
        LinearLayoutManager ms = new LinearLayoutManager(this);
        ms.setOrientation(LinearLayoutManager.HORIZONTAL);//将recyclerView的布局设置为横向
        switch (requestCode) {
   
   
      	  case 1://处理图库返回的数据
       		 if (data != null) {
   
   
       			 for (i = 0; i < data.getClipData().getItemCount(),i++) {
   
   
       			 URI.add(data.getClipData().getItemAt(i).getUri());
       				 try {
   
   
            				bitmap.add(BitmapFactory.decodeStream(getContentResolver().openInputStream(data.getClipData().getItemAt(i).getUri()), null, null));
       					 } catch (FileNotFoundException e) {
   
   
       						 e.printStackTrace();
       			 }
     		   pictureAdapter = new PictureAdapter(getApplicationContext(), bitmap);
      		  recyclerView.setLayoutManager(ms);
       		  recyclerView.setAdapter(pictureAdapter);
       		 } else {
   
   
       			 Toast.makeText(CallThePolice.this,"您未选择图片",Toast.LENGTH_SHORT).show();
        	}
        		break;
        case 2://处理相机返回的数据
        if(ImageUri==null){
   
   
       		 Toast.makeText(CallThePolice.this,"您未选择图片",Toast.LENGTH_SHORT).show();
        } else{
   
   
        try {
   
   
        	 URI.add(ImageUri);
        	 bitmap.add(BitmapFactory.decodeStream(getContentResolver().openInputStream(ImageUri)));
        } catch (FileNotFoundException e) {
   
   
      		  e.printStackTrace();
        }
        	pictureAdapter = new PictureAdapter(getApplicationContext(), bitmap);
        	recyclerView.setLayoutManager(ms);
        	recyclerView.setAdapter(pictureAdapter);
        	}
       		 break;
       	 }
        }

–4将图片上传到服务器

–1先将图片的Uri转为真实路径

public String getRealPathFromURI(Uri contentUri) {
   
   
        String res = null;
        String[] proj = {
   
    MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null);
        if(cursor.moveToFirst()){
   
   ;
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            res = cursor.getString(column_index);
        }
        cursor.close();
        return res;
    }

–2上传到服务器(用Okhttp)

    public void Upload() {
   
   

       MultipartBody.Builder builder=new MultipartBody.Builder();
        OkHttpClient okHttpClient=new OkHttpClient();
        if(URI!=null && URI.size()!=0){
   
   
            for(Uri uri:URI){
   
   
                File file=new File(getRealPathFromURI(uri));
                builder.addFormDataPart("file",file.getName(),RequestBody.create(MediaType.parse("image/jpg"),file));
            }
            MultipartBody multipartBody=builder.build();
           final Request request=new Request.Builder()
                   .url( "http://192.168.123.129:8080/ServerForAndroid/Upload")
                    .post(multipartBody)
                   .build();
            okHttpClient.newCall(request).enqueue(new Callback() {
   
   
               @Override
               public void onFailure(@NotNull Call call, @NotNull IOException e) {
   
   

                   if(e.getCause().equals(SocketTimeoutException.class))//如果超时
                   {
   
   
                       progressBar.setVisibility(View.INVISIBLE);
//                       Toast.makeText(CallThePolice.this,"上传失败",Toast.LENGTH_SHORT).show();
                   }else{
   
   
                       progressBar.setVisibility(View.INVISIBLE);
                       Looper.prepare();
                       Toast.makeText(CallThePolice.this,"上传失败",Toast.LENGTH_SHORT).show();
                       Looper.loop();
                   }
               }

               @Override
               public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
   
   
                    progressBar.setVisibility(View.INVISIBLE);
                    Looper.prepare();
                    Toast.makeText(CallThePolice.this,"上传成功",Toast.LENGTH_SHORT).show();
                    Looper.loop();
               }

           });
        }
    }

–5服务器servlet处理逻辑

–1将必要的jar包
在这里插入图片描述
这两个包必须要导入!(可以用maven下这两个包)

–2代码

package service;

import java.util.ArrayList;
import java.util.List; 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class Upload extends HttpServlet {
   
   	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
   
   
		DiskFileItemFactory factory=new DiskFileItemFactory();
		System.out.print("in");
		String path="D:\\test";
		factory.setRepository(new File(path));
		factory.setSizeThreshold(1024*1024*4);
		ServletFileUpload upload=new ServletFileUpload(factory);
		try {
   
   
			List<FileItem> list=(ArrayList<FileItem>)upload.parseRequest(request);
			for(FileItem item:list){
   
   
				if(!item.isFormField()){
   
   		
					String value = item.getName();  
                    //取到最后一个反斜杠。  
                    int start = value.lastIndexOf("\\");  
                    //截取上传文件的 字符串名字。+1是去掉反斜杠。  
                    String filename = value.substring(start+1);  
                    PrintWriter out=response.getWriter(); 
                    out.format("sj", "成功");
                    /*直接写到文件中。 */
                    item.write(new File(path,filename)); 
				}
			}		
		} catch (FileUploadException e) {
   
   
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.print(e.toString());
		} catch (Exception e) {
   
   
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.print(e.toString());
		}	
	}
}

–3图片显示

如果上传成功的话,会在D盘的test目录下,显示图片。
在这里插入图片描述

分享到: