Android Http实现文件的上传和下载

最近做一个项目,其中涉及到文件的上传和下载功能,大家都知道,这个功能实现其实已经烂大街了,遂、直接从网上荡了一堆代码用,结果,发现网上的代码真是良莠不齐,不是写的不全面,就是有问题,于是自己重新整理了一番,把它们发出来,希望更多人能受用。

文件上传

通过org.apache.commons.httpclient.HttpClient来实现文件上传,该jar包可以直接从网上所搜、下载。

   /**
     * @param mContext  上下文
     * @param targetUrl 文件上传地址
     * @param filePath  文件路径
     */
    public void uploadFile(final Activity mContext, String targetUrl, final String filePath) {

        System.out.println("targetUrl: " + targetUrl + "  filePath: " + filePath);

        if (TextUtils.isEmpty(filePath)) {
            Toast.makeText(mContext, "文件不存在", Toast.LENGTH_SHORT).show();
            return;
        }

        final PostMethod filePost = new PostMethod(targetUrl) {//这个用来中文乱码
            public String getRequestCharSet() {
                return "UTF-8";
            }
        };

        try {

            final HttpClient client = new HttpClient();

            File file = new File(filePath);

            if (file.exists() && file.isFile()) {

                long fileSize = file.length();

                if (fileSize >= 5 * 1024 * 1024) {
                    Toast.makeText(mContext, "文件不得大于5M", Toast.LENGTH_SHORT).show();
                    return;
                }

            } else {
                Toast.makeText(mContext, "文件不存在", Toast.LENGTH_SHORT).show();

                return;
            }

            // 上传文件和参数
            Part[] parts = new Part[]{new CustomFilePart(file.getName(), file),
                    new StringPart("filename", file.getName(), "UTF-8")};
            filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));

            new Thread(new Runnable() {

                @Override
                public void run() {

                    int statuscode = 0;

                    try {
                        statuscode = client.executeMethod(filePost);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    final int finalStatuscode = statuscode;

                    mContext.runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            if (finalStatuscode == HttpStatus.SC_OK) {
                                Toast.makeText(mContext, "上传成功", Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(mContext, "上传失败", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
                }

            }).start();

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

HttpClient的使用,常常会遇到乱码问题,我们主要在两个地方解决乱码问题:

  • 复写PostMethod 的getRequestCharSet,指定请求编码
final PostMethod filePost = new PostMethod(targetUrl) {//这个用来中文乱码
            public String getRequestCharSet() {
                return "UTF-8";
            }
        };
  • 自定义FilePart,指定请求参数编码
/**
 * 解决中文文件名乱码
 */
public class CustomFilePart extends FilePart {
    public CustomFilePart(String filename, File file)
            throws FileNotFoundException {
        super(filename, file);
    }

    protected void sendDispositionHeader(OutputStream out) throws IOException {
        super.sendDispositionHeader(out);
        String filename = getSource().getFileName();
        if (filename != null) {
            out.write(EncodingUtil.getAsciiBytes(FILE_NAME));
            out.write(QUOTE_BYTES);
            out.write(EncodingUtil.getBytes(filename, "UTF-8"));
            out.write(QUOTE_BYTES);
        }
    }
}

使用CustomFilePart添加参数:

Part[] parts = new Part[]{new CustomFilePart(file.getName(), file),
                    new StringPart("filename", file.getName(), "UTF-8")};
filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));

文件下载

通过HttpURLConnection下载文件。

   /**
     * @param urlStr   文件地址
     * @param path     文件保存路径
     * @param fileName 文件名
     * @return 文件的绝对路径
     */
    public String downFile(String urlStr, String path, String fileName) {

        InputStream inputStream = null;
        String filePath = null;

        try {
            FileUtils fileUtils = new FileUtils();
            //判断文件是否存在
            if (fileUtils.isFileExist(path + fileName)) {
                System.out.println("exits");
                filePath = SDPATH + path + fileName;
            } else {
                //得到io流
                inputStream = getInputStreamFromURL(urlStr);
                //从input流中将文件写入SD卡中
                File resultFile = fileUtils.write2SDFromInput(path, fileName, inputStream);
                if (resultFile != null) {

                    filePath = resultFile.getPath();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null)
                    inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return filePath;
    }

   /**
     * 根据URL得到输入流
     *
     * @param urlStr
     * @return
     */
    public InputStream getInputStreamFromURL(String urlStr) {

        HttpURLConnection urlConn;
        InputStream inputStream = null;
        try {
            url = new URL(urlStr);
            urlConn = (HttpURLConnection) url.openConnection();
            inputStream = urlConn.getInputStream();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return inputStream;
    }

文件下载其实很简单,说白了,就是通过HTTP获取InputStream ,然后通过解析InputStream 并写入到文件即可。
读取Inputstream并写入到SDCard。

/**
     * 将一个InputStream里面的数据写入到SD卡中
     *
     * @param path 文件保存路径
     * @param fileName 文件保存的名字
     * @param input 文件输入流
     * @return 文件
     */
    public File write2SDFromInput(String path, String fileName,
                                  InputStream input) {
        File file = null;
        OutputStream output = null;
        try {
            // 创建文件夹
            createSDDir(path);
            // 创建文件
            file = createSDFile(path + fileName);

            // 开启输出流,准备写入文件
            output = new FileOutputStream(file);
            // 缓冲区
            byte[] buffer = new byte[FILESIZE];
            int count;
            while ((count = input.read(buffer)) != -1) {
                // 这里,请一定按该方式写入文件,不然时而会出现文件写入错误,数据丢失问题
                output.write(buffer, 0, count);
            }
            output.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                output.close();
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

Inputstream写入到sdcard卡中,有个很重要的地方,先看下OutputStream 的write方法:
这里写图片描述
我推荐使用第二个方法write(byte[] b, int off, int len) ,目的是为了避免数据丢失。所以写文件代码如下:

 while ((count = input.read(buffer)) != -1) {
  // 这里,请一定按该方式写入文件,不然时而会出现文件写入错误,数据丢失问题
  output.write(buffer, 0, count);
}

以上便是我整理的Android Http实现文件的上传和下载方法,希望对更多的人有所帮助。

如有疑问或建议,欢迎进QQ群来讨论交流:487786925( Android研发村 )

源码地址:https://github.com/zuiwuyuan/Http_Uploader_Downloader

posted on 2016-08-07 01:54  如果蜗牛有爱情  阅读(534)  评论(0编辑  收藏  举报

导航