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卡操作需要加入操作手机外部存储的权限:


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对象,这个对象包含了文本里面的内容
     * 

*

* 从网络上下载一个文本文件的步骤: *

* 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(); } /** * 下载任意形式的文件 *

* 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得到输入流 *

* urlStr :网络链接地址 *

* 返回参数:网络连接多对应的数据流 */ 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连接得到文件的输入流三个功能。

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


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

你可能感兴趣的:(安卓)