栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

Android原生实现多线程断点下载实例代码

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android原生实现多线程断点下载实例代码

各位父老乡亲,我单汉三又回来了,今天为大家带来一个用原生的安卓写的多线程断点下载Demo。

通过本文你可以学习到:

  1. SQLite的基本使用,数据库的增删改查。
  2. Handler的消息处理与更新UI。
  3. Service(主要用于下载)的进阶与使用。
  4. 原生的json文件解析(多层嵌套)。
  5. RandomAccessFile的基本使用,可以将文件分段。
  6. 基于HttpURLConnection的大文件下载。
  7. 上面内容结合,实现多线程,断点下载。

Demo是在TV上运行的,图片显示的问题不要纠结了。

文件下载的Demo已完成,没时间上传与讲解,今天为您展示并讲解一下,纯原生的东西来下载文件,希望可以帮你理解更多安卓比较基础的问题。

我们的思路:建立一个数据库,两个表,一个用来保存网络数据,一个保存本地下载的进度等等。在点击下载按钮的时候启动DownloadService,进行比对之后下载

先看一下Demo的目录结构:

所有的步骤在代码里有非常详细的讲解,一定要看代码(下面是抽取的几个重要的类讲解)!

数据库的建立与DAO


public class DownLoadDBHelper extends SQLiteOpenHelper {
  
  public static String DATAbase_NAME = "downloadFILES.db";
  public static String TABLE_DOWNLOAD_INFO = "download_info";
  public static String TABLE_LOCALDOWNLOAD_INFO = "localdownload_info";
  private static int version = 1;
  public DownLoadDBHelper(Context context) {
    super(context, DATAbase_NAME, null, version);
  }
  @Override
  public void onCreate(SQLiteDatabase db) {
    
    db.execSQL("create table " + TABLE_DOWNLOAD_INFO + "(" + "id integer PRIMARY KEY AUTOINCREMENT," +
 "thread_id integer," + "start_position integer," + "end_position integer," + " completed_size integer," + "url varchar(100))");
    db.execSQL("create table " + TABLE_LOCALDOWNLOAD_INFO + "(" + "id integer PRIMARY KEY AUTOINCREMENT," + "name varchar(50)," +
 "url varchar(100)," + "completedSize integer," + "fileSize integer," + "status integer)");
  }
  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
    String sql = "drop table if exists " + TABLE_DOWNLOAD_INFO + "";
    String sqlOne = "drop table if exists " + TABLE_LOCALDOWNLOAD_INFO + "";
    db.execSQL(sql);
    db.execSQL(sqlOne);
    onCreate(db);//删除数据库,重新创建。这里只是简单的,并没有添加或者减少数据库中的其他字段
  }
}

DAO对数据库进行增删改查


public class Dao {
  
  private static Dao dao;
  private static DownLoadDBHelper dbHelper;
  public static final byte[] Lock = new byte[0]; //新建两个字节作为对象锁
  public static final byte[] file_Lock = new byte[0];
  public Dao() {//空构造方法,
  }
  public static synchronized Dao getInstance(Context context) {//本demo用单例模式中的懒汉模式+线程不安全 线程安全的代价是效率变低
    if (dao == null) {
      dao = new Dao();
      dbHelper = new DownLoadDBHelper(context);
    }
    return dao;
  }
  
  
  
  public boolean isExist(String url) {
    SQLiteDatabase database = dbHelper.getReadableDatabase(); //获取本app所创建的数据库
    String sql = "select count(*) from " + TABLE_LOCALDOWNLOAD_INFO + " where url=?"; //查询语句,查询总共有多少条的语句
    Cursor cursor = database.rawQuery(sql, new String[]{url});
    
    cursor.moveToFirst();
    int count = cursor.getInt(0);
    cursor.close();
    return count > 0;
  }
  
  public boolean isFirstDownload(String url) {
    SQLiteDatabase database = dbHelper.getReadableDatabase();
    String sql = "select count(*) from " + TABLE_DOWNLOAD_INFO + " where url=?";
    Cursor cursor = database.rawQuery(sql, new String[]{url});
    cursor.moveToFirst();
    int count = cursor.getInt(0);
    cursor.close();
    return count == 0;
  }
  
  public void saveInfos(List infos, Context context) {
    
    synchronized (Lock) {
      SQLiteDatabase database = dbHelper.getWritableDatabase();
      database.beginTransaction();//开启事务
      try {//如果有异常,在这里捕获
 for (DownLoadInfo info : infos) {//for循环将数据存入数据库
   String sql = "insert into " + TABLE_DOWNLOAD_INFO + "(thread_id,start_position, end_position, completed_size, url) values (?,?,?,?,?)";
   Object[] bindArgs = {info.getThreadId(), info.getStartPosition(), info.getEndPosition(), info.getCompletedSize(), info.getUrl()};
   database.execSQL(sql, bindArgs);
 }
 database.setTransactionSuccessful();//结束事务
      } catch (SQLException e) {
 e.printStackTrace();
      } finally {
 database.endTransaction();//关闭事务
      }
    }
  }
  
  public List getInfos(String urlstr) {
    List list = new ArrayList();
    SQLiteDatabase database = dbHelper.getReadableDatabase();
    String sql = "select thread_id, start_position, end_position, completed_size, url from " + TABLE_DOWNLOAD_INFO + " where url=?";
    Cursor cursor = database.rawQuery(sql, new String[]{urlstr});
    while (cursor.moveTonext()) {//通过cursor取到下载器信息,循环遍历,得到下载器集合
      DownLoadInfo info = new DownLoadInfo(cursor.getInt(0), cursor.getInt(1), cursor.getInt(2), cursor.getInt(3), cursor.getString(4));
      list.add(info);
    }
    cursor.close();
    return list;
  }
  
  public void insertFileStatus(FileStatus fileStatus) {
    synchronized (file_Lock) {//异步加开启事务,保证数据的完整性
      SQLiteDatabase database = dbHelper.getWritableDatabase();
      database.beginTransaction();
      try {
 String sql = "insert into " + TABLE_LOCALDOWNLOAD_INFO + " (name,url,completedSize,fileSize,status) values(?,?,?,?,?)";
 Object[] bindArgs = {fileStatus.getName(), fileStatus.getUrl(), fileStatus.getCompletedSize(), fileStatus.getFileSize(), fileStatus.getStatus()};
 database.execSQL(sql, bindArgs);
 database.setTransactionSuccessful();
      } catch (SQLException e) {
 e.printStackTrace();
      } finally {
 database.endTransaction();
      }
    }
  }
  
  public void updataInfos(int threadId, int compeletedSize, String urlstr, Context context) {
    synchronized (Lock) {
      String sql = "update " + TABLE_DOWNLOAD_INFO + "set completed_size = ? where thread_id =? and url=?";
      String localSql = "update " + TABLE_LOCALDOWNLOAD_INFO + "set completedSize = (select sum(completed_size) from " +
   TABLE_DOWNLOAD_INFO + "where url=? group by url ) where url=?";
      Object[] bindArgs = {compeletedSize, threadId, urlstr};
      Object[] localArgs = {urlstr, urlstr};
      SQLiteDatabase database = dbHelper.getWritableDatabase();
      database.beginTransaction();
      try {
 database.execSQL(sql, bindArgs);
 database.execSQL(localSql, localArgs);
 database.setTransactionSuccessful();
      } catch (SQLException e) {
 e.printStackTrace();
      } finally {
 database.endTransaction();
      }
    }
  }
  
  public void updateFileStatus(String url) {
    synchronized (file_Lock) {
      String sql = "update " + TABLE_LOCALDOWNLOAD_INFO + " set status = ? where url = ?";
      Object[] bindArgs = {1, url};
      SQLiteDatabase database = dbHelper.getWritableDatabase();
      database.beginTransaction();
      try {
 database.execSQL(sql, bindArgs);
 database.setTransactionSuccessful();
      } catch (SQLException e) {
 e.printStackTrace();
      } finally {
 database.endTransaction();
      }
    }
  }
  
  public List getFileStatus() {
    List list = new ArrayList();
    SQLiteDatabase database = dbHelper.getReadableDatabase();
    //String sql = "slect * from " + TABLE_LOCALDOWNLOAD_INFO + ""; //不能用,需要哪些条件就在语句中写出哪些条件
    String sql = "select name, url, status, completedSize, fileSize from " + TABLE_LOCALDOWNLOAD_INFO + "";
    Cursor cursor = database.rawQuery(sql, null);
    while (cursor.moveTonext()) {
      FileStatus fileState = new FileStatus(cursor.getString(0), cursor.getString(1), cursor.getInt(2), cursor.getInt(3), cursor.getInt(4));
      list.add(fileState);
    }
    cursor.close();
    return list;
  }
  
  public void updateFileDownStatus(int completeSize, int status, String url) {
    synchronized (file_Lock) {
      String sql = "update " + TABLE_LOCALDOWNLOAD_INFO + " set completedSize = ?,status = ? where url = ?";
      SQLiteDatabase database = dbHelper.getWritableDatabase();
      database.beginTransaction();
      try {
 Object[] bindArgs = {completeSize, status, url};
 database.execSQL(sql, bindArgs);
 database.delete(TABLE_DOWNLOAD_INFO, "url = ?", new String[]{url});
 database.setTransactionSuccessful();
      } catch (SQLException e) {
 e.printStackTrace();
      } finally {
 database.endTransaction();
      }
    }
  }
  
  public String getFileName(String url) {
    String result = "";
    String sql = "select name from " + TABLE_LOCALDOWNLOAD_INFO + " where url = ?";
    SQLiteDatabase database = dbHelper.getReadableDatabase();
    Cursor cursor = database.rawQuery(sql, new String[]{url});
    if (cursor.moveTonext()) {
      result = cursor.getString(0);
    }
    cursor.close();
    return result;
  }
  
  public void deleteFile(String url) {
    SQLiteDatabase database = dbHelper.getWritableDatabase();
    database.beginTransaction();
    try {
      database.delete(TABLE_DOWNLOAD_INFO, " url = ?", new String[]{url});
      database.delete(TABLE_LOCALDOWNLOAD_INFO, " url = ?", new String[]{url});
      database.setTransactionSuccessful();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      database.endTransaction();
    }
  }
  
  public void closeDB() {
    dbHelper.close();
  }
}

DownloadService 主要代码

@SuppressLint("HandlerLeak")
public class DownloadService extends Service
{
 public IBinder binder = new MyBinder();
 public class MyBinder extends Binder
 {
 public DownloadService getService()
 {
  return DownloadService.this;
 }
 }
 @Override
 public IBinder onBind(Intent intent)
 {
 return binder;
 }
 public static int number = 0;
 // 文件保存地址
 public final String savePath = "/mnt/sdcard/MultiFileDownload/";
 // 存放下载列表的引用
 public static List list = new ArrayList();
 public static Map localDownList = new HashMap();
 // 保存每个文件下载的下载器
 public static Map downloaders = new HashMap();
 // 每个下载文件完成的长度
 private Map completeSizes = new HashMap();
 // 每个下载文件的总长度
 private Map fileSizes = new HashMap();
 private Downloader downloader;
 private int threadCount = 5;
 private Dao dao;
 private DownLoadCallback loadCallback;
 
 private FileStatus mFileStatus = null;
 private Handler handler = new Handler()
 {
 @Override
 public void handleMessage(Message msg)
 {
  super.handleMessage(msg);
  if (msg.what == 1)
  {
  String url = (String) msg.obj;
  int length = msg.arg1;
  int completeSize = completeSizes.get(url);
  int fileSize = fileSizes.get(url);
  completeSize += length;
  completeSizes.put(url, completeSize);
  synchronized (list)
  {
   for (int i = 0; i < list.size(); i++)
   {
   FileStatus fileStatus = list.get(i);
   if (fileStatus.getUrl().equals(url))
   {
    if (completeSize == fileStatus.getFileSize())
    {
    System.out.println("-----------下载完成:"+fileStatus.getName()+":"+completeSize+"-----"+fileStatus.getFileSize());
    list.set(i, new FileStatus(fileStatus.getName(), fileStatus.getUrl(), 1, completeSize, fileStatus.getFileSize()));
    dao.updateFileDownStatus(completeSize, 1, url);
    }
    else
    {
    list.set(i, new FileStatus(fileStatus.getName(), fileStatus.getUrl(), 0, completeSize, fileStatus.getFileSize()));
    }
    mFileStatus = list.get(i);
   }
   }
   
   this.postDelayed(new Runnable()
   {
   @Override
   public void run()
   {
    if (loadCallback != null && mFileStatus != null)
    {
    loadCallback.refreshUI(mFileStatus);
    }
   }
   }, 1000);
  }
  
  }
 }
 };
 @Override
 public void onCreate()
 {
 super.onCreate();
 dao = Dao.getInstance(this);
 list = dao.getFileStatus();
 for (FileStatus fileStatus : list)
 {
  localDownList.put(fileStatus.getUrl(), fileStatus.getUrl());
 }
 
 Timer timer = new Timer();
 timer.schedule(new TimerTask()
 {
  @Override
  public void run()
  {
  number++;
  }
 }, 0, 1000);
 }
 public void download(final Button button, final String url, final String name, final Handler mHandler)
 {
 if (dao.isExist(url))
 {
  Toast.makeText(this, "别点了,已经在下载了", Toast.LENGTH_SHORT).show();
  return;
 }
 final String fileName = name + url.substring(url.lastIndexOf("."));
 new Thread(new Runnable()
 {
  @Override
  public void run()
  {
  downloader = downloaders.get(url);
  if (downloader == null)
  {
   downloader = new Downloader(url, savePath, fileName, threadCount, DownloadService.this, handler);
   downloaders.put(url, downloader);
  }
  if (downloader.isDownloading())
   return;
  
  LoadInfo loadInfo = downloader.getDownloaderInfors();
  
  if(loadInfo != null)
  {
   FileStatus fileStatus = new FileStatus(fileName, url, 0, loadInfo.getComplete(), loadInfo.getFileSize());
   dao.insertFileStatus(fileStatus);
   completeSizes.put(url, loadInfo.getComplete());
   fileSizes.put(url, fileStatus.getFileSize());
   list.add(fileStatus);
   localDownList.put(url, url);
   downloader.download();
   Message msg = new Message();
   msg.what = 1;
   msg.obj = button;
   mHandler.sendMessage(msg);
  }
  else
  {
   Message msg = new Message();
   msg.what = 2;
   msg.obj = button;
   mHandler.sendMessage(msg);
  }
  }
 }).start();
 }
 
 //暂停下载
 public void Pause(Downloader downloader)
 {
 downloader.pause();
 }
 
 //继续下载
 public void reDownload(final Button button, final String url, final String name, final Handler mHandler)
 {
 new Thread(new Runnable()
 {
  @Override
  public void run()
  {
  String fileName = dao.getFileName(url);
  
  downloader = downloaders.get(url);
  if (downloader == null)
  {
   downloader = new Downloader(url, savePath, fileName, threadCount, DownloadService.this, handler);
   downloaders.put(url, downloader);
  }
  if (downloader.isDownloading())
   return;
  
  LoadInfo loadInfo = downloader.getDownloaderInfors();
  
  if(loadInfo != null && !fileName.equals(""))
  {
   if(!completeSizes.containsKey(url))
   {
   completeSizes.put(url, loadInfo.getComplete());
   }
   if(!fileSizes.containsKey(url))
   {
   fileSizes.put(url, loadInfo.getFileSize());
   }
   downloader.download();
   Message msg = new Message();
   msg.what = 1;
   msg.obj = button;
   mHandler.sendMessage(msg);
  }
  else
  {
   Message msg = new Message();
   msg.what = 2;
   msg.obj = button;
   mHandler.sendMessage(msg);
  }
  }
 }).start();
 }
 
 public void delete(final String url)
 {
 Downloader down = downloaders.get(url);
 if(down != null)
 {
  down.pause();
 }
 
 handler.postDelayed(new Runnable()
 {
  @Override
  public void run()
  {
  dao.deleteFile(url);
  
  for (int i = 0; i < list.size(); i++)
  {
   FileStatus fileStatus = list.get(i);
   if (fileStatus.getUrl().equals(url))
   {
   list.remove(i);
   }
  }
  
  localDownList.remove(url);
  downloaders.remove(url);
  completeSizes.remove(url);
  fileSizes.remove(url);
  
  if(loadCallback != null)
  {
   loadCallback.deleteFile(url);
  }
  }
 }, 1000);
 }
 public interface DownLoadCallback
 {
 public void refreshUI(FileStatus fileStatus);
 
 public void deleteFile(String url);
 }
 public void setLoadCallback(DownLoadCallback loadCallback)
 {
 this.loadCallback = loadCallback;
 }
}

下载工具类DownLoadUtil


public class DownLoadUtil {
  
  private String downPath;// 下载路径
  private String savePath;// 保存路径
  private String fileName;// 文件名称
  private int threadCount;// 线程数
  private Handler mHandler;
  private Dao dao;
  private Context context;
  private int fileSize;// 文件大小
  private int range;
  private List infos;// 存放下载信息类的集合
  private int state = INIT;
  private static final int INIT = 1;// 定义三种下载的状态:初始化状态,正在下载状态,暂停状态
  private static final int DOWNLOADING = 2;
  private static final int PAUSE = 3;
  
  public DownLoadUtil(String downPath, String savePath, String fileName, int threadCount, Handler mHandler, Context context) {
    this.downPath = downPath;
    this.savePath = savePath;
    this.fileName = fileName;
    this.threadCount = threadCount;
    this.mHandler = mHandler;
    this.context = context;
    dao = Dao.getInstance(context);
  }
  
  public boolean isPause() {
    return state == PAUSE;
  }
  
  public boolean isDownloading() {
    return state == DOWNLOADING;
  }
  
  private boolean isFirst(String url) {
    return dao.isFirstDownload(url);
  }
  
  public LoadItemInfo getDownloadInfos() {
    if (isFirst(downPath)) {
      if (initFirst()) {//如果是第一次下载的话,要进行初始化,1.获得下载文件的长度 2.创建文件,设置文件的大小
 range = this.fileSize / this.threadCount;
 infos = new ArrayList();
 //这里就是启动多线程下载,看出来了吗?配合RandomAccessFile。每一个DownLoadInfo就是RandomAccessFile文件的一部分
 for (int i = 0; i < this.threadCount - 1; i++) {
   DownLoadInfo info = new DownLoadInfo(i, i * range, (i + 1) * range - 1, 0, downPath);
   infos.add(info);
 }
 DownLoadInfo info = new DownLoadInfo(this.threadCount - 1, (this.threadCount - 1) * range, this.fileSize, 0, downPath);
 infos.add(info);
 dao.saveInfos(infos, this.context);
 //(String urlDownload, int completePercent, int fileSize)
 LoadItemInfo loadInfo = new LoadItemInfo(this.downPath, 0, this.fileSize);
 return loadInfo;
      } else {
 return null;
      }
    } else {
      //不是第一次下载,我们应该怎么做呢?从数据库里面取回来
      infos = dao.getInfos(this.downPath);
      if (infos != null && infos.size() > 0) {
 int size = 0;
 int completeSize = 0;
 for (DownLoadInfo info : infos) {
   completeSize += info.getCompletedSize();
   size += info.getEndPosition() - info.getStartPosition() + this.threadCount - 1;
 }
 LoadItemInfo loadInfo = new LoadItemInfo(this.downPath, completeSize, size);
 return loadInfo;
      } else {
 return null;
      }
    }
  }
  // 设置暂停
  public void pause() {
    state = PAUSE;
  }
  // 重置下载状态,将下载状态设置为init初始化状态
  public void reset() {
    state = INIT;
  }
  
  private boolean initFirst() {
    boolean result = true;
    HttpURLConnection conn = null;
    RandomAccessFile randomFile = null;
    URL url = null;
    try {
      url = new URL(downPath);
      conn = (HttpURLConnection) url.openConnection();
      conn.setConnectTimeout(5 * 1000);
      conn.setRequestMethod("GET");
      // 如果http返回的代码是200或者206则为连接成功
      if (conn.getResponseCode() == 200 || conn.getResponseCode() == 206) //状态码(206),表示服务器已经执行完部分对资源的GET请求
      {
 fileSize = conn.getContentLength();// 得到文件的大小
 if (fileSize <= 0) {
   //("网络故障,无法获取文件大小");
   return false;
 }
 File dir = new File(savePath);
 // 如果文件目录不存在,则创建
 if (!dir.exists()) {
   if (dir.mkdirs()) {
     //("mkdirs success.");
   }
 }
 File file = new File(this.savePath, this.fileName);
 randomFile = new RandomAccessFile(file, "rwd");
 randomFile.setLength(fileSize);// 设置保存文件的大小
 randomFile.close();
 conn.disconnect();
      }
    } catch (Exception e) {
      e.printStackTrace();
      result = false;
    } finally {
      if (randomFile != null) {
 try {
   randomFile.close();
 } catch (IOException e) {
   e.printStackTrace();
 }
      }
      if (conn != null) {
 conn.disconnect();
      }
    }
    return result;
  }
  
  public void downLoad() {
    if (infos != null) {
      if (state == DOWNLOADING) {
 return;
      }
      state = DOWNLOADING;// 把状态设置为正在下载
      for (DownLoadInfo info : infos) {//为什么说我们是多线程呢?因为我们分别用新线程去下载刚才分割好的一个RandomAccessFile文件
 new DownLoadThread(info.getThreadId(), info.getStartPosition(), info.getEndPosition(), info.getCompletedSize(), info.getUrl(), this.context).start();
      }
    }
  }
  
  public class DownLoadThread extends Thread {
    private int threadId;
    private int startPostion;
    private int endPostion;
    private int compeletedSize;
    private String url;
    private Context context;
    public static final int PROGRESS = 1;
    public DownLoadThread(int threadId, int startPostion, int endPostion, int compeletedSize, String url, Context context) {//构造方法,传入特定的参数
      this.threadId = threadId;
      this.startPostion = startPostion;
      this.endPostion = endPostion;
      this.compeletedSize = compeletedSize;
      this.url = url;
      this.context = context;
    }
    //开始下载
    @Override
    public void run() {
      HttpURLConnection conn = null;
      RandomAccessFile randomAccessFile = null;
      InputStream inStream = null;
      File file = new File(savePath, fileName);
      URL url = null;
      try {
 url = new URL(this.url);
 conn = (HttpURLConnection) url.openConnection();
 constructConnection(conn);
 if (conn.getResponseCode() == 200 || conn.getResponseCode() == 206) {
   randomAccessFile = new RandomAccessFile(file, "rwd");
   randomAccessFile.seek(this.startPostion + this.compeletedSize);//RandomAccessFile移动指针,到需要下载的块
   inStream = conn.getInputStream();
   byte buffer[] = new byte[4096];//这个4096为么子呢?我也不知道,就是看阿里的人下载apk的时候都用4096,我也用
   int length = 0;
   while ((length = inStream.read(buffer, 0, buffer.length)) != -1) {
     randomAccessFile.write(buffer, 0, length);
     compeletedSize += length;
     // 更新数据库中的下载信息
     dao.updataInfos(threadId, compeletedSize, this.url, this.context);
     // 用消息将下载信息传给进度条,对进度条进行更新
     Message message = Message.obtain();
     message.what = PROGRESS;
     message.obj = this.url;
     message.arg1 = length;
     mHandler.sendMessage(message);// 给DownloadService发送消息
     if (state == PAUSE) {
//("-----pause-----");
return;
     }
   }
   // ("------------线程:" + this.threadId + "下载完成");
 }
      } catch (IOException e) {
 e.printStackTrace();
 //("-----下载异常-----"); 这里下载异常我就不处理了,你可以发一条重新下载的消息
      } finally {//用完只后流要关闭,不然容易造成资源抢占,内存泄漏
 try {
   if (inStream != null) {
     inStream.close();
   }
   if (randomAccessFile != null) {
     randomAccessFile.close();
   }
   if (conn != null) {
     conn.disconnect();
   }
 } catch (IOException e) {
   e.printStackTrace();
 }
      }
    }
    
    private void constructConnection(HttpURLConnection conn) throws IOException {
      conn.setConnectTimeout(5 * 1000);// 设置连接超时5秒
      conn.setRequestMethod("GET");// GET方式提交,如果你是用post请求必须添加 conn.setDoOutput(true); conn.setDoInput(true);
      conn.setRequestProperty(
   "Accept",
   "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
      conn.setRequestProperty("Accept-Language", "zh-CN");
      conn.setRequestProperty("Referer", this.url);
      conn.setRequestProperty("Charset", "UTF-8");
      int startPositionNew = this.startPostion + this.compeletedSize;
      // 设置获取实体数据的范围
      conn.setRequestProperty("Range", "bytes=" + startPositionNew + "-" + this.endPostion);
      conn.setRequestProperty(
   "User-Agent",
   "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
      conn.setRequestProperty("Connection", "Keep-Alive");
      conn.connect();
    }
  }
}

Github地址:https://github.com/Shanlovana/DownLoadFiles/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/158681.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号