zoukankan      html  css  js  c++  java
  • android网络编程之HttpUrlConnection的讲解--实现文件的断点上传

    1、网络开发不要忘记在配置文件中添加访问网络的权限

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

    2、网络请求、处理不能在主线程中进行,一定要在子线程中进行。因为网络请求一般有1~3秒左右的延时,在主线程中进行造成主线程的停顿,对用户体验来说是致命的。(主线程应该只进行UI绘制,像网络请求、资源下载、各种耗时操作都应该放到子线程中)。

    3、Android端程序

    public class MoreUploadActivity extends Activity {
        private TextView mTvMsg;
        
        private String result = "";
        
        private long start = 0;           // 开始读取的位置
        private long stop = 1024 * 1024;  // 结束读取的位置
        private int times = 0;            //读取次数
        
        private long fileSize = 0;  //文件大小
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_times_upload);
            
            initView();
        }
        
        private void initView(){
            mTvMsg = (TextView) findViewById(R.id.tv_upload);
            
            try {
                FileInputStream file = new FileInputStream(Environment.getExternalStorageDirectory().getPath() + "/aaaaa/baidu_map.apk");
                fileSize = file.available();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            new Thread(uploadThread).start();
        }
        
        private Thread uploadThread = new Thread(){
            public void run() {
                HttpURLConnection connection = null;
                try {
                    URL url = new URL("http://192.168.23.1:8080/TestProject/MoreUploadTest");
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("POST");
                    connection.setChunkedStreamingMode(51200);
                    connection.setUseCaches(false);
                    // 设置允许输出
                    connection.setDoOutput(true);
                    // 设置断点开始,结束位置
                    connection.setRequestProperty("Range", "bytes=" + start + "-" + stop);
                    
                    String path = Environment.getExternalStorageDirectory().getPath() + "/aaaaa/baidu_map.apk";
                    RandomAccessFile file = new RandomAccessFile(path, "rw");                
                    file.seek(start);
                    byte[] buffer = new byte[1024];
                    int count = 0;
                    OutputStream os = connection.getOutputStream();
                    if(fileSize > 1024*1024){
                        for(int i=0; i<1024 && count!=-1; i++){
                            count = file.read(buffer);
                            os.write(buffer, 0, count);
                        }
                    }else{
                        for(int i=0; i<(fileSize/1024)+1 && count!=-1; i++){
                            count = file.read(buffer);
                            os.write(buffer, 0, count);
                        }
                    }
                    os.flush();
                    os.close();
                    
                    Log.e("ABC", connection.getResponseCode() + "");
                    if(connection.getResponseCode() == 200){
                        result += StringStreamUtil.inputStreamToString(connection.getInputStream()) + "
    ";
                    }
                    
                    start = stop + 1;
                    stop += 1024*1024;
                    fileSize -= 1024*1024;
                    
                    Message msg = Message.obtain();
                    msg.what = 0;
                    uploadHandler.sendMessage(msg);
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if(connection != null){
                        connection.disconnect();
                    }
                }
            };
        };
        
        private Handler uploadHandler = new Handler(){
            public void handleMessage(android.os.Message msg) {
                if(msg.what == 0){
                    if(times >= 8){
                        mTvMsg.setText(result);
                    }else{
                        times += 1;
                        new Thread(uploadThread).start();
                        mTvMsg.setText(result);
                    }
                }
            };
        };
    }

    4、服务器端使用Servlet开发,这里只给出doPost()方法

    public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String range = request.getHeader("Range");
            int start = Integer.parseInt(range.substring(6, range.indexOf("-")));
            int stop = Integer.parseInt(range.substring(range.indexOf("-")+1, range.length()));
            
            RandomAccessFile file = new RandomAccessFile("F:/JavaWeb/TestProject/WebRoot/files/baidu.apk", "rw");
            file.seek(start);
            InputStream is = request.getInputStream();
            byte[] buffer = new byte[1024];
            int count = 0;
            while((count=is.read(buffer)) != -1){
                file.write(buffer, 0, count);
            }
            if(is != null){
                is.close();
            }
            if(file != null){
                file.close();
            }
            
            response.setContentType("text/html");
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();
            out.println("文件上传成功" + start + "-" + stop);
            out.flush();
            out.close();
        }

    5、最主要的就是一:设置断点setRequestProperty("Range", "bytes=0-1024"),获取断点request.getHeader("Range")

                         二:通过RandomAccessFile来读写文件

    6、对于输出流的三个方法的对比:

        os.write(byte[] buffer);   可能出现错误,因为你每次读取的数据小于等于1024,但你每次写入的数据仍然是1024, 对图片有一定影响,对安装包绝对是致命的影响。
        os.write(int oneByte);     效率低
        os.write(byte[] buffer, int byteOffset, int byteCount);   效率高,和第二个方法相比有一个数量级的差别(主观上看,有兴趣的可以测几下)。

    7、参考博文:http://blog.sina.com.cn/s/blog_413580c20100wmr8.html

  • 相关阅读:
    2017-2018 ACM-ICPC, Asia Tsukuba Regional Contest E:Black or White
    树状数组--二叉索引树
    P1654 OSU!-洛谷luogu
    P1365 WJMZBMR打osu! / Easy-洛谷luogu
    P4550 收集邮票-洛谷luogu
    P2257 YY的GCD--洛谷luogu

    P3200 [HNOI2009]有趣的数列--洛谷luogu
    catalan数
    lucas定理
  • 原文地址:https://www.cnblogs.com/begin1949/p/5060974.html
Copyright © 2011-2022 走看看