在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?

在 Activity 中实现 getContentView 操作

Java中实现图片的上传