`
AnhuiOSS技术分享
  • 浏览: 34975 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Android 文件下载

阅读更多

    Android开发中经常会遇到文件的下载,而下载的时间与网络状态和被下载文件的大小等因素有关。本文会对单线程下载和多线程下载做简要说明。无论哪种操作,最终都是基于HTTP(HTTPS)的网络访问。

 

    先看看基本的一个操作流程,然后对于每一个操作步骤逐一实现就可以了。

    基本流程:

  1. 设置连接属性;
  2. 建立连接;
  3. 获得需要的资源;
  4. 释放资源;

    说明:这个流程是相对的,每个人可以根据具体情况而定。:)

 

    1、在普通Java项目中下载文件: 为了简化问题,我们先不考虑在Android中实现过程,仅仅实现一个下载并保存网络资源的操作。

    代码如下:

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class FileDownload {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		downloadFile("http://image.tianjimedia.com/uploadImages/2012/153/2H4Y79KZF2X3.jpg", "image.jpg");
		downloadFile("http://www.google.com", "message.txt");
		
	}
	
	private static void downloadFile(String urlPath, String filePath) {
		
		InputStream inputStream = null;
		ByteArrayOutputStream byteArrayOutputStream = null;
		byte[] data = null;
		try {
			URL url = new URL(urlPath);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(6 * 1000);
                        conn.connect();
                        if (conn.getResponseCode() == 200) {
				inputStream = conn.getInputStream();
				byteArrayOutputStream = new ByteArrayOutputStream();
				byte[] buffer = new byte[1024];
				int length = -1;
				while ((length = inputStream.read(buffer)) != -1) {
					byteArrayOutputStream.write(buffer, 0, length);
				}
				data = byteArrayOutputStream.toByteArray();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			if (byteArrayOutputStream != null) {
				try {
					byteArrayOutputStream.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		
		if (data != null) {
			File file = new File(filePath);
			FileOutputStream outputStream = null;
			try {
				outputStream = new FileOutputStream(file);
				outputStream.write(data);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (outputStream != null) {
					try {
						outputStream.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
		
	}

}

     说明:

        1、InputStream inputStream = null;和ByteArrayOutputStream byteArrayOutputStream = null;之所以在try-catch外定义,是为了可以在finally代码块中可以访问,并释放该资源。在回收资源时,最好把不同资源放在单独的try-catch块中做资源释放操作,否则可能造成资源泄漏。

		InputStream inputStream = null;
		ByteArrayOutputStream byteArrayOutputStream = null;
		try {

			......

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
                                if (inputStream != null) {
			        	inputStream.close();
		        	}
			        if (byteArrayOutputStream != null) {
				        byteArrayOutputStream.close();
			         }
                        } catch (Exception e) {
                                 e.printStackTrace();
                        }
		}

     如果采用上述资源释放代码,当inputStream和byteArrayOutputStream都不为null时,如果inputStream.close();发生异常,将导致byteArrayOutputStream.close();不被执行,从而没有释放该资源。

        2、conn.setRequestMethod("GET");和conn.setConnectTimeout(6 * 1000);是设置连接属性。还有其它属性,如果需要的话,可以进行设定。

        3、conn.connect();建立连接。

        4、conn.getInputStream();获得连接后的输入流,从中可以获得数据。

        5、在finally代码块中对申请的资源进行释放。

    运行该项目,会在项目的根目录下看到两个文件,image.jpg和message.txt,如图所示:



    2、在Android项目中下载文件:

    a、对UI的设计:



    主Activity中有两个Button,分别启动另外的两个Activity,来实现图片的下载显示和网页内容的获得并显示。布局文件就补贴出来了,会在附件中提供源码。

    b、主Activity没有什么好说的,下面对另外两个Activity做详细说明:

    DownloadImageActivity:

package com.anhuioss.download;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;

public class DownloadImageActivity extends Activity implements OnClickListener {
	
	private EditText filePathEditText;
	private Button downloadButton;
	private ImageView imageDisplay;
	
	private Handler handler = new Handler();
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_download_image);
		
		filePathEditText = (EditText) findViewById(R.id.adi_image_path);
		downloadButton = (Button) findViewById(R.id.adi_button_download);
		imageDisplay = (ImageView) findViewById(R.id.adi_image);
		
		downloadButton.setOnClickListener(this);
		
	}

	@Override
	public void onClick(View v) {
		if (v == downloadButton) {
			if (!Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
				return;
			}
			String path = filePathEditText.getText().toString();
			if (!TextUtils.isEmpty(path)) {
				downloadButton.setEnabled(false);
				imageDisplay.setImageDrawable(null);
				downloadFile(path, Environment.getExternalStorageDirectory() + File.separator + "image.jpg");
			}
		}
	}
	
	private void downloadFile(final String urlPath, final String filePath) {
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				
				InputStream inputStream = null;
				ByteArrayOutputStream byteArrayOutputStream = null;
				byte[] data = null;
				try {
					URL url = new URL(urlPath);
					HttpURLConnection conn = (HttpURLConnection) url.openConnection();
					conn.setRequestMethod("GET");
					conn.setConnectTimeout(6 * 1000);
					conn.connect();
					if (conn.getResponseCode() == 200) {
						inputStream = conn.getInputStream();
						byteArrayOutputStream = new ByteArrayOutputStream();
						byte[] buffer = new byte[1024];
						int length = -1;
						while ((length = inputStream.read(buffer)) != -1) {
							byteArrayOutputStream.write(buffer, 0, length);
						}
						data = byteArrayOutputStream.toByteArray();
					}
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					if (inputStream != null) {
						try {
							inputStream.close();
						} catch (IOException e1) {
							e1.printStackTrace();
						}
					}
					if (byteArrayOutputStream != null) {
						try {
							byteArrayOutputStream.close();
						} catch (IOException e1) {
							e1.printStackTrace();
						}
					}
				}
				
				if (data != null) {
					File file = new File(filePath);
					FileOutputStream outputStream = null;
					try {
						outputStream = new FileOutputStream(file);
						outputStream.write(data);
						handler.post(new Runnable() {
							
							@Override
							public void run() {
								
								downloadButton.setEnabled(true);
								Drawable drawable = null;
								try {
									drawable = Drawable.createFromPath(filePath);
								} catch (Error e) {
									e.printStackTrace();
								}
								imageDisplay.setImageDrawable(drawable);
								
							}
						});
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						if (outputStream != null) {
							try {
								outputStream.close();
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					}
				}
				
			}
		}).start();
		
	}
	
}

    说明:

        1、private Handler handler = new Handler();handler的作用是在下载线程中完成下载后在UI线程里面更新UI。

        2、由于示例中需要用到SDCARD,所以在做下载操作时,如果没有挂载SDCARD时,不进行下载处理:

if (!Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
      return;
}

        3、

handler.post(new Runnable() {
	
	@Override
	public void run() {
		
		downloadButton.setEnabled(true);
		Drawable drawable = null;
		try {
			drawable = Drawable.createFromPath(filePath);
		} catch (Error e) {
			e.printStackTrace();
		}
		imageDisplay.setImageDrawable(drawable);
		
	}
});

     利用handler的post方法,在UI线程里面更新UI。首先使能按钮,其次创建drawable,最后显示图片。

 

    3、运行项目,查看效果: 在运行前,不要忘记在Manifest文件中添加网络访问和访问SDCARD的权限哦!

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

     下载图片的效果如下:



 

    获取网页内容的页面效果:


 

 

 

 

    4、多线程文件下载,直接看普通Java项目中相关操作的代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

public class FileDownloadMultiThread {

	public static void main(String[] args) {
		
		downloadFile();
		
	}
	
	private static void downloadFile() {
		
		String fileName = "mysql.chm";
		String urlPath = "http://192.168.1.106/mysql.chm";
		
		// 下载开始前,创建RandomAccessFile并设置文件大小
		RandomAccessFile file = null;
		try {
			
			// 创建URL对象
			URL url = new URL(urlPath);
			
			// 创建HttpURL连接
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			
			// 设置请求属性
			conn.setConnectTimeout(6 * 1000);
			conn.setRequestMethod("GET");
			
			// 连接
			conn.connect();
			
			// 需要下载文件的长度
			int fileLength = conn.getContentLength();
			
			// 创建RandomAccessFile并设置文件大小
			file = new RandomAccessFile(fileName, "rw");
			file.setLength(fileLength);
			
			// 启动的线程数量
			int threadCount = 6;
			
			// 计算每个线程需要下载数据的长度
			int threadDownloadLength = fileLength % 3 == 0 ? fileLength / 3 : fileLength / 3 + 1;
			
			// 创建threadCount个下载线程
			for (int i = 0; i < threadCount; i++) {
				// 计算开始位置
				int startPosition = i * threadDownloadLength;
				// 创建匿名下载线程对象
				new MultiDownloadThread(fileName, urlPath, startPosition).start();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 资源释放
			if (file != null) {
				 try {
					file.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		
	}
	
	static class MultiDownloadThread extends Thread {
		
		private String urlPath;
		private int startPosition;
		private RandomAccessFile accessFile;
		
		public MultiDownloadThread(String fileName, String urlPath, int startPosition) {
			this.urlPath = urlPath;
			this.startPosition = startPosition;
			try {
				accessFile = new RandomAccessFile(fileName, "rw");
				accessFile.seek(startPosition);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		public void run () {
			
			InputStream inputStream = null;
			try {
				
				URL url = new URL(urlPath);
				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
				conn.setConnectTimeout(6 * 1000);
				conn.setRequestMethod("GET");
				
				// 设置HTTP的Range字段,指定该线程从文件的什么位置开始下载
				conn.setRequestProperty("Range", "bytes=" + startPosition + "-");
				
				conn.connect();
				inputStream = conn.getInputStream();
				
				byte[] buffer = new byte[1024];
				int readLength = -1;
				int totalLength = 0;
				while ((readLength = inputStream.read(buffer)) != -1) {
					accessFile.write(buffer, 0, readLength);
					totalLength = totalLength + readLength;
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (accessFile != null) {
					try {
						accessFile.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (inputStream != null) {
					try {
						inputStream.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			
		}
		
	}

}

     说明:

        1、RandomAccessFile类创建目标文件并设置文件大小;

        2、HttpURLConnection.setRequestProperty("Range", "bytes=" + startPosition + "-");方法指定下载位置;

        3、RandomAccessFile.seek();设置文件指针偏移量,保存下载内容到指定位置;

        4、由于线程的创建和销毁过程,线程之间的上下文切换等都需要系统资源,所以threadCount不是越大越好,而是根据具体情况进行设定;

        4、在Android上实现多线程下载的方法类似,注意Android环境的特性就可以了,再次不再赘述!:)

 

        5、多说一句: HTTP(HTTPS)的连接到网络上的数据资源的方式和设置多种多样,本例仅仅是从一个角度进行说明,希望对你有所帮助!如果需要Android项目源码,请查看附件!:)

 

 

  • 大小: 11.6 KB
  • 大小: 29 KB
  • 大小: 27.7 KB
  • 大小: 25.2 KB
  • 大小: 145.8 KB
  • 大小: 20.6 KB
  • 大小: 19.5 KB
  • 大小: 65.5 KB
分享到:
评论

相关推荐

    一个Android文件下载Download程序示例

    一个Android文件下载Download程序示例,文件会下载至local端,远程安装程序(请输入URL),取得远程文件,取得URL,创建连接,InputStream 下载文件,创建临时文件,取得站存盘案路径,将文件写入暂存盘,在手机上打开文件的...

    Android文件下载(实现断点续传)

    综上所述,实现Android文件的断点续传下载主要依赖于Java的RandomAccessFile类和多线程技术,通过精确控制文件的读写位置和下载范围,确保下载的连续性和可靠性。这种技术不仅提高了用户的下载体验,也在一定程度上...

    Android文件下载示例

    与网上流传一个itcast的多线程下载的示例不同, ...可能需要进一步优化,本示例下载同样大小的文件需要6-7秒(下载速度都是200K左右) 暂不支持断点、多个文件同时下载, 架构清晰,可重复利用,如有问题欢迎斧正

    Android文件下载Demo(可断点续传)

    本示例"Android文件下载Demo(可断点续传)"提供了一个实现多线程下载并且支持断点续传功能的源代码DEMO。下面将详细解释这个Demo中涉及的关键知识点。 1. **多线程下载**: 在Android中,为了提高文件下载速度,...

    android下载word文档并打开

    在Android平台上,开发一个应用程序以实现下载Word文档并顺利打开是一项常见的需求。下面将详细讲解这一过程中的关键知识点,以及如何结合给定的资源进行操作。 1. **Android权限管理**: 在Android中,访问网络和...

    android文件下载(实现断点续传)

    在Android平台上,文件下载是一项常见的任务,特别是在处理大型文件或多媒体资源时,为了提升用户体验,开发者通常会采用多线程下载并实现断点续传功能。断点续传允许用户在下载过程中暂停、恢复,避免因网络问题或...

    安卓文件下载上传解压相关-android文件下载存储demo.rar

    最后,这个压缩包中的“android文件下载存储demo”项目,尽管可能需要自行调试才能运行,但它提供了一种基础结构,你可以从中学习如何组织代码、如何处理网络请求,以及如何在Android环境中实现文件的存取和解压。...

    android文件下载

    十分有用的共享资源十分有用的共享资源十分有用的共享资源。

    java和android文件下载 断点续传概要.pdf

    Java 和 Android 文件下载断点续传概要 在本文中,我们将对 Java 和 Android 文件下载断点续传的概要进行详细的介绍。断点续传是一种常用的文件下载技术,它可以在下载过程中发生意外中断时,继续从中断的地方继续...

    Java和Android文件下载断点续传和图片下载

    java和Android文件下载断点续传和图片下载代码实现, 可直接复制代码, 实现多种文件下载,

    Downloader,下载程序是一个轻量级的强大的android文件下载库。.zip

    下载程序下载器,下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理...

    android文档下载

    在Android平台上实现文档下载功能,特别是对于Word文档的下载,是一项常见的需求,尤其对于移动应用开发者来说。这个“android文档下载”主题主要涉及到以下几个关键知识点: 1. **Android权限管理**: 在Android...

    Android文件断点下载案例

    在Android开发中,断点下载是一项重要的功能,它允许用户在中断网络连接后从上次停止的位置继续下载大文件,如应用程序、音乐或视频。本文将深入探讨如何在Android平台上实现断点下载,包括其原理、步骤以及核心代码...

    Android利用Http下载文件

    在Android平台上,利用Http协议进行文件下载是一项常见的任务,它涉及到网络编程、多线程、文件操作等多个技术领域。本文将深入探讨如何在Android中实现这个功能,主要围绕标题“Android利用Http下载文件”和提供的...

    android通过Service进行文件下载,后台下载

    本教程将深入探讨如何利用Service组件在Android设备上实现文件的后台下载,确保即使用户退出应用程序,文件下载也能继续进行。 ### 1. Android Service基础知识 Service是Android四大组件之一,它在后台运行,没有...

    Android 端本地预览 PDF 文件

    Android 端本地预览 PDF 文件,使用 AS2.3.3 Gradle 4.1 下载下来可以直接编译运行,内部支持加载本地 File ,也可以加载一个 URL 类型的 PDF 文件,如果恰恰你的 APP 不想调用第三方软件的话 这个 DEMO 非常适合你...

    android文件下载存储demo

    这个demo演示从网上下载文件并保存到手机,demo中可以下载一个XML文件并在Console窗口输出,还可以下载一个MP3文件并保存到手机存储目录中的BoBoMusic文件夹中,下载保存成功会返回:0。(XML和MP3文件我已经传到...

    基于Java开发的Android文件下载工具-JarvisDownloader设计源码

    该项目为基于Java开发的Android文件下载工具,命名为JarvisDownloader,设计源码包含69个文件,涵盖22个Java源代码文件、21个XML布局文件、10个PNG资源文件、4个Gradle配置文件、3个Git忽略配置文件及其他类型文件。...

    Android开发文档6.0(最新)-分卷1

    官网最新Android API开发文档,为不方便下载的亲打包上传,一共6个分卷,解压任意一个,文档无加密。文档为HTML类型。

    Android TCP文件下载

    在Android开发中,TCP文件下载是一项常见的任务,它涉及到网络通信、多线程处理以及文件操作等技术。本文将详细讲解如何实现一个Android应用,利用TCP协议从PC服务器下载文件到Android设备。 首先,理解TCP...

Global site tag (gtag.js) - Google Analytics