Android Studio第17课——Http协议网络文件下载

小白一个,有很多不懂的地方。

先上一个界面Activity代码

    /**声明控件*/
    private Button downloadTxt;
    private Button downloadFile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /**找到控件*/
        downloadTxt = findViewById(R.id.downloadTxt);
        downloadFile = findViewById(R.id.downloadFile);

        /**绑定监听器*/
        downloadTxt.setOnClickListener(new downloadTxtListener());
        downloadFile.setOnClickListener(new downloadFileListener());

    }

    class downloadTxtListener implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            HttpDownloader httpDownloader = new HttpDownloader();
            String string =httpDownloader.download("http://www.9ku.com/downlrc.php?id=668803");
            System.out.println(string);
        }
    }

    class downloadFileListener implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            HttpDownloader httpDownloader = new HttpDownloader();
            int result = httpDownloader.downloadFile(
                    "http://61.136.107.33/file3.data.weipan.cn/68505953/85f20f855a5d5707abf0ce587c6c58e6feed6b75?ip=1530198740,123.13.202.228&ssig=QnYrXxebAC&Expires=1530199340&KID=sae,l30zoo1wmz&fn=R.City%26Adam+Levine-Locked+Away.mp3&se_ip_debug=123.13.202.228&from=1221134&wsrid_tag=5b34f625_xiangwangtong30_32119-44031&wsiphost=local","111","111");
            System.out.println(result);
        }
    }

上图功能简单,一个按钮用来从网络上下载文本文件;一个按钮用来从网络上下载任何形式的文件;

再上SD卡部分的代码:

package com.example.urien.httpdownload;

import android.os.Environment;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FileUtils {
    private String SDPATH;

    public String getSDPATH() {
        return SDPATH;
    }

    public FileUtils() {
        /**得到当前外部存储设备的根目录*/
        SDPATH = Environment.getExternalStorageDirectory() + "/";
    }

    /**
     * 在SD卡上创建文件
     */
    public File creadSDFile(String fileName) throws IOException {
        File file = new File(SDPATH + fileName);
        file.createNewFile();
        return file;
    }

    /**
     * 在SD卡上创建目录
     */
    public File creadSDDir(String dirName) {
        File dir = new File(SDPATH + dirName);
        dir.mkdir();
        return dir;
    }

    /**
     * 判断SD卡上的文件是否存在
     */
    public boolean isFileExist(String fileName) {
        File file = new File(SDPATH + fileName);
        return file.exists();
    }

    /**
     * 讲一个InputStream里面的数据写到SD卡中
     * path :写入的路径(目录)
     * fileName :文件名
     * inputStream  :携带数据的输入流
     *
     * 返回值 File:写入后的文件所对应的对象
     */
    public File writeInputStream2SD(String path, String fileName, InputStream inputStream) {
        File file = null;
        OutputStream outputStream = null;
        try {
            /**
             * 要讲一个文件写到SD卡里面
             * 1.先创建一个目录
             * 2.在这个目录里面创建一个文件
             * 3.把要写入的文件数据写到创建好的文件里面
             * */
            //创建一个目录
            creadSDDir(path);
            //创建一个文件
            file = creadSDFile(path + fileName);
            //根据这个文件对象创建一个输出流,这个输出流将会对这个文件写入数据
            outputStream = new FileOutputStream(file);
            //创建一个4K的字节缓存
            byte buffer[] = new byte[1024 * 4];
            /**
             * 先从输入流里面读取4K字节数据到buffer里面
             * 再把这个数据通过输出流写入到文件中
             * 每次读写4K直到全部读取并写入完毕
             * */
            while ((inputStream.read(buffer) != -1)) {
                outputStream.write(buffer);
            }
            //操作完毕后晴空下输出流
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭输出流
                outputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }
}

这里面包含了有很多封装好的功能方法:比如取得SDCARD路径、判断SDCARD路径文件是否存在、向SD卡创建文件、创建目录、向指定路径写入文件等等,中文注释也很详细。

注意SD卡操作需要加入操作手机外部存储的权限:

<!--添加读写SD卡的权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

最后上Http部分代码:

package com.example.urien.httpdownload;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class HttpDownloader {
    /**
     * 声明一个URL对象
     */
    private URL url = null;

    /**
     * 根据URL下载文件,下载的文件需要是文本文件
     * urlStr :网络链接地址
     * 返回值是一个String对象,这个对象包含了文本里面的内容
     * <p>
     * <p>
     * 从网络上下载一个文本文件的步骤:
     * <p>
     * 1.创建一个URL对象
     * 2.通过URL对象,创建一个HttpURLConnection对象
     * 3.得到InputSteam
     * 4.从InputStream当中读取数据
     */
    public String download(String urlStr) {

        /**声明一个字符串数组对象*/
        StringBuffer stringBuffer = new StringBuffer();
        String line = null;

        /**生成一个BufferedReader对象,
         * 这个类里面有一个readLine方法很好用
         * 可以每次读取一行数据
         * */
        BufferedReader bufferedReader = null;
        try {
            /**创建一个URL对象,传入参数为网络下载地址
             * 这样可以生成一个代表这个网络地址的URL对象
             * */
            url = new URL(urlStr);
            /**创建一个Http连接
             * 这个对象就代表了这个网络地址的一个http链接
             * */
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

            /**
             * httpURLConnection.getInputStream() 以字节的方式读取需要下载文件
             * InputStreamReader 把一个字节流转换成字符流
             * BufferedReader 把字符流套上一个BufferedReader装饰方便一行一行的读取
             */
            bufferedReader = new BufferedReader(
                    new InputStreamReader(
                            httpURLConnection.getInputStream()
                    )
            );
            /**
             * 以行为单位读取数据,每次读取一行,并把这一行字符返回到line中
             * 当line不为null指针,说明line里面有数据
             * 这时候变把读取的的这行字符line对象添加到将要返回的stringBuffer中
             * 当字符读取完毕,readLine方法没有读取到数据便返回一个null,此时跳出while
             * */
            while ((line = bufferedReader.readLine()) != null) {
                stringBuffer.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bufferedReader.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return stringBuffer.toString();
    }

    /**
     * 下载任意形式的文件
     * <p>
     * urlStr   :需要下载文件的文件网络下载链接
     * path     :下载完文件后所存放的SD卡里面的目录
     * FileName :下载好后文件的命名
     * 整形返回值
     * -1   下载文件出错
     * 0    下载文件成功
     * 1    代表文件已经存在
     */
    public int downloadFile(String urlStr, String path, String fileName) {

        /**声明一个输入流*/
        InputStream inputStream = null;
        try {
            //生成一个FileUtils对象
            FileUtils fileUtils = new FileUtils();

            if (fileUtils.isFileExist(path + fileName)) {
                return 1;//文件已经存在了
            } else {
                //得到网络下载地址多对应的下载链接
                inputStream = getInputStreamFromUrl(urlStr);

                //向SD卡写入得到输入流
                File file = fileUtils.writeInputStream2SD(path,fileName,inputStream);
                if(file == null)
                    return -1;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        } finally {
            try{
                inputStream.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return 0;
    }

    /**
     * 根据url得到输入流
     * <p>
     * urlStr   :网络链接地址
     * <p>
     * 返回参数:网络连接多对应的数据流
     */
    public InputStream getInputStreamFromUrl(String urlStr)
            throws MalformedURLException, IOException {

        //通过下载链接作为参数得到一个URL的对象
        url = new URL(urlStr);

        //调用url的openConnection方法得到一个代表这个下载链接的http链接对象
        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

        //通过这个http链接得到这个链接所对应的输入流
        InputStream inputStream = httpURLConnection.getInputStream();
        return inputStream;
    }
}

这里面包含有通过url连接下载文本类型的文件;通过url链接下载任意形式的文件、通过url连接得到文件的输入流三个功能。

注意这里要添加手机的访问网络权限:

<!--添加访问网络的权限-->
<uses-permission android:name="android.permission.INTERNET"/>

因为知识有限,测试的app并没有成功从网络上下载文件。更不会搭建服务器,所以一切都是迷茫。点击按钮LogCat打印出的信息如下:

06-28 23:00:56.586 15138-15138/com.example.urien.httpdownload D/libc-netbsd: [getaddrinfo]: hostname=www.9ku.com; servname=(null); cache_mode=(null), netid=0; mark=0
    [getaddrinfo]: ai_addrlen=0; ai_canonname=(null); ai_flags=4; ai_family=0
06-28 23:13:21.401 15138-15138/com.example.urien.httpdownload D/libc-netbsd: [getaddrinfo]: hostname=61.136.107.33; servname=(null); cache_mode=(null), netid=0; mark=0
    [getaddrinfo]: ai_addrlen=0; ai_canonname=(null); ai_flags=4; ai_family=0
06-28 23:13:21.402 15138-15138/com.example.urien.httpdownload D/libc-netbsd: [getaddrinfo]: hostname=61.136.107.33; servname=(null); cache_mode=(null), netid=0; mark=0

    [getaddrinfo]: ai_addrlen=0; ai_canonname=(null); ai_flags=4; ai_family=0

如果有知道的大神,还请指教,十分感谢。

By Urien 2018年6月28日 23:14:09

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值