在fragment中实现Android上传图片至本地JavaWeb服务器
Posted 石墨方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在fragment中实现Android上传图片至本地JavaWeb服务器相关的知识,希望对你有一定的参考价值。
服务器端:
需要一个接受文件的servlet,以及导入两个包:commons-fileupload-1.3.1.jar 和 commons-io-2.4.jar
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.List; 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.FileItemFactory; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class Upload extends HttpServlet { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ try{ request.setCharacterEncoding("UTF-8"); // 设置处理请求参数的编码格式 response.setContentType("text/html;charset=UTF-8"); // 设置Content-Type字段值 PrintWriter out = response.getWriter(); //下面的代码开始使用Commons-UploadFile组件处理上传的文件数据 FileItemFactory factory = new DiskFileItemFactory(); // 建立FileItemFactory对象 ServletFileUpload upload = new ServletFileUpload(factory); //分析请求,并得到上传文件的FileItem对象 List<FileItem> items = upload.parseRequest(request); //从web.xml文件中的参数中得到上传文件的路径 String uploadPath = "E:\\\\A_HW\\\\"; File file = new File(uploadPath); if (!file.exists()) { file.mkdir(); } String filename = ""; // 上传文件保存到服务器的文件名 InputStream is = null; // 当前上传文件的InputStream对象 //循环处理上传文件 for (FileItem item : items) { //处理普通的表单域 if (item.isFormField()) { if (item.getFieldName().equals("imageFile")) //图片文件的name { //如果新文件不为空,将其保存在filename中 if (!item.getString().equals("")) filename = item.getString("UTF-8"); } } //处理上传文件 else if (item.getName() != null && !item.getName().equals("")) { //从客户端发送过来的上传文件路径中截取文件名 filename = item.getName().substring( item.getName().lastIndexOf("\\\\") + 1); is = item.getInputStream(); // 得到上传文件的InputStream对象 } } //将路径和上传文件名组合成完整的服务端路径 filename = uploadPath + filename; //如果服务器已经存在和上传文件同名的文件,则输出提示信息 if (new File(filename).exists()) { new File(filename).delete(); } //开始上传文件 if (!filename.equals("")) { //用FileOutputStream打开服务端的上传文件 FileOutputStream fos = new FileOutputStream(filename); byte[] buffer = new byte[8192]; // 每次读8K字节 int count = 0; //开始读取上传文件的字节,并将其输出到服务端的上传文件输出流中 while ((count = is.read(buffer)) > 0) { fos.write(buffer, 0, count); // 向服务端文件写入字节流 } fos.close(); // 关闭FileOutputStream对象 is.close(); // InputStream对象 out.println("文件上传成功!"); } }catch (Exception e) { e.printStackTrace(); } } }
注意:imageFile要和之后android端名字的对应
客户端:
我是直接通过拍照获取的图片,所以首先获取图片的位置
private void doTakePhoto() { Intent intent = new Intent(); // 指定开启系统相机的Action intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); intent.addCategory(Intent.CATEGORY_DEFAULT); String time = String.valueOf(System.currentTimeMillis()); // 根据文件地址创建文件 File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/M2_test/" + time + ".jpg"); Log.i("Environment_path", Environment.getExternalStorageDirectory().getAbsolutePath()); file.getParentFile().mkdirs(); if (file.exists()) { file.delete(); } // 把文件地址转换成Uri格式 Uri uri2 = Uri.fromFile(file); Uri uri = FileProvider.getUriForFile(getContext(), "com.f.myapplication", file); //添加权限 Log.i("uri",uri.toString()); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //临时授权 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, REQUEST_CAMERA); String imagePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/M2_test/" + time + ".jpg"; imageCheck(uri2,imagePath); iniLocationMap(); // uploadImage(imagePath); }
获取到的图片进行查看,通过bundle传递image的uri
private void imageCheck(Uri uri,String img) { String imagepath = uri.toString(); Image_check image_check = new Image_check(); Bundle bundle = new Bundle(); bundle.putString("imagepath", imagepath); bundle.putString("img",img); image_check.setArguments(bundle); ft.replace(R.id.fragment_content,image_check); //这个是我fragment替换 ft.addToBackStack(null); ft.commit(); }
Image_check是一个Fragment可以查看图片并通过点击按钮实现上传文件(需要点击预览图片,获取到图片位置,才能上传图片)
public class Image_check extends Fragment { private EditText et_beizhu; private Button btn_upload; private Button btn_look_pic; private ImageView iv; private FragActivity_Map fragActivity_map; String imagepath=""; String img; private FragmentManager fm; private FragmentTransaction ft; public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.image_check, container, false); fm = getFragmentManager(); ft = fm.beginTransaction(); fragActivity_map=new FragActivity_Map(); iv=view.findViewById(R.id.imageView); btn_upload= view.findViewById(R.id.btn_upload); btn_look_pic= view.findViewById(R.id.btn_look_pic); if (getArguments() != null) { imagepath = getArguments().getString("imagepath"); Log.i("image_check_image",imagepath); } btn_look_pic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { iv.setImageURI( Uri.parse(imagepath) ); } }); btn_upload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { uploadImage(imagepath); FragActivity_Map frag_map = new FragActivity_Map(); Bundle bundle = new Bundle(); bundle.putString("result_image", "ok_upload"); frag_map.setArguments(bundle); fm.beginTransaction().hide(Image_check.this).show(fragActivity_map).commit(); // ft.replace(R.id.fragment_content,frag_map); ft.addToBackStack(null); ft.commit(); } }); return view; } //线程上传图片 private void uploadImage(String imagePath) { Log.i("start upload", "start upload"); Log.i("start upload_path", "imagePath" + imagePath); NetworkTask networkTask = new NetworkTask(); networkTask.execute(imagePath); } public static Image_check newInstance(String text) { Image_check fragment = new Image_check(); Bundle bundle = new Bundle(); bundle.putString("imagepath", text); fragment.setArguments(bundle); return fragment; } }
NetworkTask 是一个实现连接javaweb服务器的线程并调用上传文件的工具类 UploadUtil
class NetworkTask extends AsyncTask<String, Integer, String> { // 这里就是JavaWeb服务器地址,servlet private final String ServerURL="http://192.168.1.105:8080/File_upload/Upload"; @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(String... params) { // return doPost(params[0]); String uri = (params[0]); Uri u=Uri.parse((String) uri); File file = new File(u.getPath()); return UploadUtil.uploadFile(file, ServerURL); } @Override protected void onPostExecute(String result) { if (UploadUtil.SUCCESS.equalsIgnoreCase(result)) { Log.i("上传结果", "上传成功 "); } else { Log.i("上传结果", "上传失败 "); } } }
UploadUtil工具类(啊哈,网上找的)
public class UploadUtil { private static final int TIME_OUT = 10 * 10000000; //超时时间 private static final String CHARSET = "utf-8"; //设置编码 public static final String SUCCESS = "1"; public static final String FAILURE = "0"; public static String uploadFile(File file, String RequestURL) { String BOUNDARY = UUID.randomUUID().toString(); //边界标识 随机生成 String PREFIX = "--", LINE_END = "\\r\\n"; try { URL url = new URL(RequestURL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(TIME_OUT); conn.setConnectTimeout(TIME_OUT); conn.setDoInput(true); //允许输入流 conn.setDoOutput(true); //允许输出流 conn.setUseCaches(false); //不允许使用缓存 conn.setRequestMethod("POST"); //请求方式 conn.setRequestProperty("Charset", CHARSET); //设置编码 conn.setRequestProperty("connection", "keep-alive"); conn.setRequestProperty("Content-Type", "multipart/form-data" + ";boundary=" + BOUNDARY); if (file != null) { OutputStream outputSteam = conn.getOutputStream(); DataOutputStream dos = new DataOutputStream(outputSteam); StringBuffer sb = new StringBuffer(); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); /** * 这里重点注意: * name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件 * filename是文件的名字,包含后缀名的 比如:abc.png */ Log.i("file.getName()",file.getName()); sb.append("Content-Disposition: form-data; name=\\"imageFile\\"; filename=\\"" + file.getName() + "\\"" + LINE_END); sb.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINE_END); sb.append(LINE_END); dos.write(sb.toString().getBytes()); InputStream is = new FileInputStream(file); byte[] bytes = new byte[1024]; int len = 0; while ((len = is.read(bytes)) != -1) { dos.write(bytes, 0, len); } is.close(); dos.write(LINE_END.getBytes()); byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes(); dos.write(end_data); dos.flush(); dos.close(); /** * 获取响应码 200=成功 * 当响应成功,获取响应的流 */ int res = conn.getResponseCode(); Log.e("response code", "response code:" + res); if (res == 200) { return SUCCESS; } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return FAILURE; } }
当然当中遇到了很多问题,必须要仔仔细细看错误提示啊
注意
- 开了Tomcat服务器后,要关闭电脑的防火墙,要不然可能连接不上
以上是关于在fragment中实现Android上传图片至本地JavaWeb服务器的主要内容,如果未能解决你的问题,请参考以下文章
Android Studio:如何从 Fragment 在 ActionBar 中实现后退按钮
如何在 Fragments 中实现 onBackPressed()?
Android 在fragment中实现返回键单击提醒 双击退出
如何在 Fragment 中实现一个按钮并让它打开一个新的 Activity?