第一次做这种拍照并上传服务器的项目,遇到了很多问题,查了又查,问了又问,之前运用流的方式上传服务器,但是由于忘记增加读取Android的SD卡权限了,以失败告终,最后通过OkHttp框架上传 ,也是没有增加权限,最后发现问题增加权限之后可以上传了,应该用流的方式增加权限之后应该也可以上传吧,但是比较了一下,运用OkHttp框架上传比较简单、快捷、代码量少。最后决定写了这个关于(Android拍照并通过OkHttp框架上传服务器)的博客。希望帮助到初次接触该方面的初学者!
第一:配置AndroidManifest.java权限
这个将照片写入SD卡Android权限配置是这次我遇到的最大的困难,因为初次拍照片上传服务器不知道写入SD卡还需要权限,所以花费了好长时间将照片写入SD卡写入失败,调试了三个小时,最后在大佬的一句提醒中“写入Android是不是需要权限”,然后在百度查了一下,果然有权限(细节往往在编程中很重要) 权限如下:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
第二:启动Android相机拍照并上传服务器
import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.support.annotation.Nullable; import android.view.View; import android.widget.Toast; import com.squareup.okhttp.Callback; import com.squareup.okhttp.MediaType; import com.squareup.okhttp.MultipartBuilder; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.RequestBody; import com.squareup.okhttp.Response; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.IOException; /** * Created by Boy Baby on 2018/4/8. * */ public class MainActivity extends Activity { //声明变量 String photoPath1; private static final String TAG = "MaintenanceActivity"; private static String photo_URL = "http://ip:8080/javaweb1/QPhotoServlet";//服务器API private String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "mms" ;//获取自定义SD路径 private File photo_file=new File(path);//生成该路径的文件 private String photoPath; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //添加okhttp对象 OkHttpClient mOkHttpClent = new OkHttpClient(); } /**\ * 功能:拍照 (启动相机) * @param view */ public void Btn_photo(View view){ //判断该路径文件在SD卡中是否存在 if (!photo_file.exists()) { photo_file.mkdirs(); } photo_file = new File(path, "/temp.jpg"); photoPath = path + "/temp.jpg"; Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (photo_file != null) { //启动相机拍照 captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo_file)); startActivityForResult(captureIntent, 1); // 参数 1 作为页面标识 } } //回调方法 protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode==1) { //这中情况下 data是为null的,因为自定义了路径 所以通过这个路径来获取 Bitmap smallBitmap = BitmapUtil.getSmallBitmap(photoPath); //Android版本不同所用到的MultipartBody MultipartBuilder对象不同 我用的版本android 3.0以上 所以用的MultipartBuilder MultipartBuilder multipartBuilder = new MultipartBuilder() .type(MultipartBuilder.FORM) .addFormDataPart("img", "temp.jpg", //第一个参数是标识 服务器端通过该标识拿到照片 RequestBody.create(MediaType.parse("image/png"), photo_file)); RequestBody requestBody = multipartBuilder.build(); Request request = new Request.Builder() .url(photo_URL) //服务器URL .post(requestBody) .build(); executeRequest(request); } } //服务器回调 private void executeRequest(Request request) { //3.将Request封装为Call com.squareup.okhttp.Call call = new OkHttpClient().newCall(request); //4.执行call call.enqueue(new Callback() { @Override//回调错误时 public void onFailure(Request request, IOException e) { Toast.makeText(MainActivity.this,"网络连接失败!",Toast.LENGTH_LONG).show(); } @Override//回调成功时 public void onResponse(Response response) throws IOException { final String relsult = response.body().string();//接收服务器返回来的信息 try { JSONObject jsonObject = new JSONObject(relsult); String rel = jsonObject.getString("result"); if(rel.equals("1")){ }else { } } catch (JSONException e) { e.printStackTrace(); } } }); }}
第三:在这里附加Servlet接收照片的服务器端代码:
public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
request.setCharacterEncoding("utf-8"); //设置编码
//获得磁盘文件条目工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//获取文件需要上传到的路径
String path = request.getRealPath("/upload");
File file=new File(path);
if(!file.exists()){
file.mkdirs();
}
factory.setRepository(new File(path));
//设置 缓存的大小
factory.setSizeThreshold(1024*1024) ;
//文件上传处理
ServletFileUpload upload = new ServletFileUpload(factory);
try {
//可以上传多个文件
List<FileItem> list = (List<FileItem>)upload.parseRequest(request);
for(FileItem item : list){
//获取属性名字
String name = item.getFieldName();
//如果获取的 表单信息是普通的 文本 信息
if(item.isFormField()){
//获取用户具体输入的字符串,因为表单提交过来的是 字符串类型的
String value = item.getString() ;
request.setAttribute(name, value);
}else{
//获取路径名
String value = item.getName() ;
//索引到最后一个反斜杠
int start = value.lastIndexOf("\\");
//截取 上传文件的 字符串名字,加1是 去掉反斜杠,
String filename = value.substring(start+1);
request.setAttribute(name, filename);
//写到磁盘上
item.write( new File(path,filename) );//第三方提供的
System.out.println("上传成功:"+filename);
response.getWriter().print(filename);//将路径返回给客户端
}
}
} catch (Exception e) {
System.out.println("上传失败");
response.getWriter().print("上传失败:"+e.getMessage());
}
}
有什么错误或不足之处下方评论欢迎来评论!