android 文件夹 下载,Android 文件下载(1)

1.项目用到的图片上传的关键方法:

哈喽,我又来了,现在是2021年1月19号上午10点35分,给大家分享些文件上传的方法,有需要的继续往下看呦!

1.普通单线程下载文件:

直接使用URLConnection.openStream()打开网络输入流,然后将流写入到文件中!

核心方法:

public static void downLoad(String path,Context context)throws Exception

{

URL url = new URL(path);

InputStream is = url.openStream();

//截取最后的文件名

String end = path.substring(path.lastIndexOf("."));

//打开手机对应的输出流,输出到文件中

OutputStream os = context.openFileOutput("Cache_"+System.currentTimeMillis()+end, Context.MODE_PRIVATE);

byte[] buffer = new byte[1024];

int len = 0;

//从输入六中读取数据,读到缓冲区中

while((len = is.read(buffer)) > 0)

{

os.write(buffer,0,len);

}

//关闭输入输出流

is.close();

os.close();

}

运行结果:

712c0acfd938

image

712c0acfd938

image

2.普通多线程下载:

我们都知道使用多线程下载文件可以更快地完成文件的下载,但是为什么呢?

答:因为抢占的服务器资源多,假设服务器最多服务100个用户,服务器中的一个线程 对应一个用户100条线程在计算机中并发执行,由CPU划分时间片轮流执行,加入a有99条线程 下载文件,那么相当于占用了99个用户资源,自然就有用较快的下载速度

PS:当然不是线程越多就越好,开启过多线程的话,app需要维护和同步每条线程的开销, 这些开销反而会导致下载速度的降低,另外还和你的网速有关!

多线程下载的流程:

获取网络连接

本地磁盘创建相同大小的空文件

计算每条线程需从文件哪个部分开始下载,结束

依次创建,启动多条线程来下载网络资源的指定部分

[图片上传中...(image-5ec007-1611024089841-0)]

PS:这里直接创建一个Java项目,然后在JUnit里运行指定方法即可,

核心代码如下:

public class Downloader {

//添加@Test标记是表示该方法是Junit测试的方法,就可以直接运行该方法了

@Test

public void download() throws Exception {

//设置URL的地址和下载后的文件名

String filename = "meitu.exe";

String path = "http://10.13.20.32:8080/Test/XiuXiu_Green.exe";

URL url = new URL(path);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(5000);

conn.setRequestMethod("GET");

//获得需要下载的文件的长度(大小)

int filelength = conn.getContentLength();

System.out.println("要下载的文件长度" + filelength);

//生成一个大小相同的本地文件

RandomAccessFile file = new RandomAccessFile(filename, "rwd");

file.setLength(filelength);

file.close();

conn.disconnect();

//设置有多少条线程下载

int threadsize = 3;

//计算每个线程下载的量

int threadlength = filelength % 3 == 0 ? filelength / 3 : filelength + 1;

for (int i = 0; i < threadsize; i++) {

//设置每条线程从哪个位置开始下载

int startposition = i * threadlength;

//从文件的什么位置开始写入数据

RandomAccessFile threadfile = new RandomAccessFile(filename, "rwd");

threadfile.seek(startposition);

//启动三条线程分别从startposition位置开始下载文件

new DownLoadThread(i, startposition, threadfile, threadlength, path).start();

}

int quit = System.in.read();

while ('q' != quit) {

Thread.sleep(2000);

}

}

private class DownLoadThread extends Thread {

private int threadid;

private int startposition;

private RandomAccessFile threadfile;

private int threadlength;

private String path;

public DownLoadThread(int threadid, int startposition,

RandomAccessFile threadfile, int threadlength, String path) {

this.threadid = threadid;

this.startposition = startposition;

this.threadfile = threadfile;

this.threadlength = threadlength;

this.path = path;

}

public DownLoadThread() {}

@Override

public void run() {

try

{

URL url = new URL(path);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setConnectTimeout(5000);

conn.setRequestMethod("GET");

//指定从什么位置开始下载

conn.setRequestProperty("Range", "bytes="+startposition+"-");

//System.out.println(conn.getResponseCode());

if(conn.getResponseCode() == 206)

{

InputStream is = conn.getInputStream();

byte[] buffer = new byte[1024];

int len = -1;

int length = 0;

while(length < threadlength && (len = is.read(buffer)) != -1)

{

threadfile.write(buffer,0,len);

//计算累计下载的长度

length += len;

}

threadfile.close();

is.close();

System.out.println("线程"+(threadid+1) + "已下载完成");

}

}catch(Exception ex){System.out.println("线程"+(threadid+1) + "下载出错"+ ex);}

}

}

}

}

运行截图:

如图,使用多线程完成了对文件的下载!双击exe文件可运行,说明文件并没有损坏!

712c0acfd938

image

712c0acfd938

image

注意事项:

int filelength = conn.getContentLength(); //获得下载文件的长度(大小)

RandomAccessFile file = new RandomAccessFile(filename, "rwd"); //该类运行对文件进行读写,是多线程下载的核心

nt threadlength = filelength % 3 == 0 ? filelength/3:filelength+1; //计算每个线程要下载的量

conn.setRequestProperty("Range", "bytes="+startposition+"-"); //指定从哪个位置开始读写,这个是URLConnection提供的方法

//System.out.println(conn.getResponseCode()); //这个注释了的代码是用来查看conn的返回码的,我们前面用的都是200, 而针对多线程的话,通常是206,必要时我们可以通过调用该方法查看返回码!

int quit = System.in.read();while('q' != quit){Thread.sleep(2000);} //这段代码是做延时操作的,因为我们用的是本地下载,可能该方法运行完了,而我们的 线程还没有开启,这样会引发异常,这里的话,让用户输入一个字符,如果是'q'的话就退出

3.使用DownloadManager更新应用并覆盖安装:

下面的代码可以直接用,加入到项目后,记得为这个内部广播注册一个过滤器:

AndroidManifest.xml

import android.app.DownloadManager;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.content.pm.ApplicationInfo;

import android.content.pm.PackageManager;

import android.database.Cursor;

import android.net.Uri;

import android.os.Bundle;

import android.os.Environment;

import android.support.v7.app.AppCompatActivity;

public class UpdateAct extends AppCompatActivity {

//这个更新的APK的版本部分,我们是这样命名的:xxx_v1.0.0_xxxxxxxxx.apk

//这里我们用的是git提交版本的前九位作为表示

private static final String FILE_NAME = "ABCDEFGHI";

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

String endpoint = "";

try {

//这部分是获取AndroidManifest.xml里的配置信息的,包名,以及Meta_data里保存的东西

ApplicationInfo info = getPackageManager().getApplicationInfo(

getPackageName(), PackageManager.GET_META_DATA);

//我们在meta_data保存了xxx.xxx这样一个数据,是https开头的一个链接,这里替换成http

endpoint = info.metaData.getString("xxxx.xxxx").replace("https",

"http");

} catch (PackageManager.NameNotFoundException e) {

e.printStackTrace();

}

//下面的都是拼接apk更新下载url的,path是保存的文件夹路径

final String _Path = this.getIntent().getStringExtra("path");

final String _Url = endpoint + _Path;

final DownloadManager _DownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

DownloadManager.Request _Request = new DownloadManager.Request(

Uri.parse(_Url));

_Request.setDestinationInExternalPublicDir(

Environment.DIRECTORY_DOWNLOADS, FILE_NAME + ".apk");

_Request.setTitle(this.getString(R.string.app_name));

//是否显示下载对话框

_Request.setShowRunningNotification(true);

_Request.setMimeType("application/com.trinea.download.file");

//将下载请求放入队列

_DownloadManager.enqueue(_Request);

this.finish();

}

//注册一个广播接收器,当下载完毕后会收到一个android.intent.action.DOWNLOAD_COMPLETE

//的广播,在这里取出队列里下载任务,进行安装

public static class Receiver extends BroadcastReceiver {

public void onReceive(Context context, Intent intent) {

final DownloadManager _DownloadManager = (DownloadManager) context

.getSystemService(Context.DOWNLOAD_SERVICE);

final long _DownloadId = intent.getLongExtra(

DownloadManager.EXTRA_DOWNLOAD_ID, 0);

final DownloadManager.Query _Query = new DownloadManager.Query();

_Query.setFilterById(_DownloadId);

final Cursor _Cursor = _DownloadManager.query(_Query);

if (_Cursor.moveToFirst()) {

final int _Status = _Cursor.getInt(_Cursor

.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));

final String _Name = _Cursor.getString(_Cursor

.getColumnIndexOrThrow("local_filename"));

if (_Status == DownloadManager.STATUS_SUCCESSFUL

&& _Name.indexOf(FILE_NAME) != 0) {

Intent _Intent = new Intent(Intent.ACTION_VIEW);

_Intent.setDataAndType(

Uri.parse(_Cursor.getString(_Cursor

.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI))),

"application/vnd.android.package-archive");

_Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

context.startActivity(_Intent);

}

}

_Cursor.close();

}

}

}

4.参考代码下载:

喜欢是可乐妹呦的文章就点个👍呦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android学习文档 1 一、Android前言 3 1、Android发展历程 3 2、Android发展前景 8 3、Android 应用领域 9 二、准备工作 11 1、 Android开发环境搭建 11 1.1 第一种搭建Android的开发环境步骤: 12 1.2 第二种搭建Android的开发环境步骤: 12 2、AVD设备(模拟器) 13 3、Android的模拟器Emulator 14 4、DDMS调试 14 5、Android开发需知 14 5.1 Android目录结构 14 5.2 UI控件: 15 5.3 应用程序权限 15 6、第一个android应用程序 15 7、Android组件介绍 20 三、Android应用程序架构分析 21 1、Android布局组件介绍及其实例分析 21 2.1 布局组件概述 21 2.1.1 五大布局: 21 2.1.2 属性: 21 2.1.3 常用的长度单位解析: 21 2.2 线性布局 22 2.3 表格布局 22 2.4 相对布局 23 2.5 基本界面组件 23 2、Activity生命周期及其实例分析 24 1.1 Avtivity介绍 24 1.2 Activity的生命周期 25 1.2.1 Activity的三种状态 25 1.2.2 Activity在三种状态切换时调用的方法(7种) 25 1.2.3 Activity跳转与布局管理器 27 1.2.4 Activity中与跳转相关的方法 28 1.2.5 Activity的内部切换界面 28 1.2.6 Activity的用法 28 1.3 Avtivity的回调机制 28 四、事件处理机制 29 1、事件效果 29 2、事件监听器的处理模型 30 3、监听器的事件处理模型步骤 31 4、事件监听器必须实现事件监听器接口 31 5、实现事件监听器 31 6、基于回调的事件处理 32 7、基于回调的事件传播 32 五、 Android数据存储 32 1、android的数据存储 32 2、如何在android中使用SQlite数据库? 33 2.1 使用SharedPreferences 33 2.2 练习使用SharedPreferences 33 3、要读写其他应用的SharedPreferences怎么做? 33 六、 Json数据格式解析和xml解析 34 1、JSON简介 34 2、Gson介绍 34 3、JSON与XML 34 4、Android中对xml的解析 35 4.1 学习json数据格式,编写xml文件转化成实体bean的工具类 35 1.先写一个工具类,把list集合转化成xml格式,注意支持各种类型 35 分析:用dom4j来操作 35 2.涉及的知识 35 五、开发中会用到的技术 36 1、Selector技术 36 2、Tosat显示消息提示框技术 36 3、Handler消息传递机制 36 4、Handler类的主要作用 37 六、Android实例 38 1、做多米播放器的特效 38 2、做时钟的特效 39 1. 涉及的知识 40 一、完成”时钟”应用程序的操作 43 七、图形与图像处理 44

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值