1. 程式人生 > >Android 從網路上下載檔案以及寫入到SDcard裡面

Android 從網路上下載檔案以及寫入到SDcard裡面

通過FilegetOutputStream(file)  獲取OutputStream 物件

通過HttpURlConnection.getInputStream() 獲取InputStream物件  

 本節課講述如何使用Android應用程式在網路上下載檔案。

   比如說一個背單詞的應用,詞庫更新,還有音樂播放器之類的都需要這個功能。

   1.如何使用HTTP協議下載檔案

   2.將下載的檔案寫入SDCARD

   FTP HTTP 等很多協議都可以實現下載檔案,我們當然也是可以將下載檔案放入主儲存檔案,但是由於儲存空間限制,我們一般放置帶SD卡里。

  檔案下載步驟

1.建立一個HttpURLConnection

物件

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

2.獲得一個輸入流InputStream物件

  java中牽涉到檔案操作一定逃不開輸入流輸出流,輸入流是向程式讀入檔案,輸出流是向目標寫出檔案。

3.訪問網路的許可權

  android.permission.INTERNET

  這個需要在manifest當中進行修改

本次課的程式一共有三個類  

Download.java

HttpDownloader.java

FileUtils.java

DownLoad.java 是主程式

HttpDownloader.java  是封裝好的下載工具類

FileUtils.java    是為了將資料寫入到SD卡當中所用到的輔助工具類 可以收藏

HttpDownloader這個類當中有三個方法

有兩個download函式 但是引數  返回值都不同  是過載關係

public String download(String urlStr)

·這個函式的引數是一個可下載文字檔案的連結 返回一個String型別,就是連結所代表的資料。當然這個函式當中牽涉到了很多javaIO流操作知識。

  首先宣告一個StringBuffer物件 (StringBuffer  String 其實是差不多的 不過 有區別)

還有一個String 物件  還有一個 

BufferedReader物件 

StringBuffer sb = new StringBuffer();

String line = null;

BufferedReader buffer = null;  //為了使用它的readLine()方法

/**

 * 根據URL下載檔案,前提是這個檔案當中的內容是文字,函式的返回值就是檔案當中的內容

 * 1.建立一個URL物件

 * 2.通過URL物件,建立一個HttpURLConnection物件

 * 3.得到InputStram

 * 4.從InputStream當中讀取資料

 * @param urlStr

 * @return

 */

首先我們要獲取一個URL物件(用於建立下載檔案所需的HttpURLConnection物件)

private URL url = null;

url = new URL(urlStr);

這樣我們就得到了一個代表輸入引數urlStr地址的URL物件

下一步

// 建立一個Http連線

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

我們呼叫URLopenConnection()方法(並且通過向下轉型)來獲取一個HttpURLConnection物件

這個物件就代表了Http的連線

下面進行IO劉操作

// 使用IO流讀取資料

buffer = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));

//urlConn.getInputStream() 代表的就是這個地址的檔案

while ((line = buffer.readLine()) != null) {

sb.append(line); 

              }

使用HttpURLConnection物件的getInputStream() 方法來獲取InputStream物件(代表著目標檔案與應用程式的連線通道,資料通過管道進入手機)

由於直接操作InputStream 不是很方便  所以要在外面套上一層InputStreamReader  再套上 BufferedReader 

原因是由於InputStream 是一個位元組流,也就說讀入的資料都是一個個位元組,所以通過InputStreamReader 我們就可以把位元組流轉換為字元流,但是一個個處理字元還是不方便,於是又套上了BufferedReader,他有一個readLine可以一次性讀取一行資料,很方便,讀完之後返回null

所以通過StringBuffer append就可以新增資料回來

這樣就完成了 (前提是文字檔案)

總結一下,我們

第一步要做的事情是構造一個URL物件,利用URL的建構函式,將我們要下載檔案的地址放在建構函式當中,形成了一個我們要下載檔案物件的URL物件。

第二步我們利用這個URL物件建立一個HttpURlConnection物件,這個物件代表著我們的應用程式與目標檔案之間的連線,這是構造了一個http連線(呼叫URLopenConnection方法,然後通過向下轉型就可以了)。

第三步利用HttpURlConnection物件的getInputStream方法 獲得InputStream物件

由於Android把各種類封裝的很好,這樣就很容易實現了,但是現在這個方法只是將文字讀取出來,並沒有寫入到SD卡里面。

/**

 * 根據URL下載檔案,前提是這個檔案當中的內容是文字,函式的返回值就是檔案當中的內容

 * 1.建立一個URL物件

 * 2.通過URL物件,建立一個HttpURLConnection物件

 * 3.得到InputStram

 * 4.從InputStream當中讀取資料

 * @param urlStr

 * @return

 */

public String download(String urlStr) {

StringBuffer sb = new StringBuffer();

String line = null;

BufferedReader buffer = null;

private URL url = null;

try {

// 建立一個URL物件,代表這個地址

url = new URL(urlStr);

// 建立一個Http連線

HttpURLConnection urlConn = (HttpURLConnection) url

.openConnection();

// 使用IO流讀取資料

buffer = new BufferedReader(new InputStreamReader(urlConn

.getInputStream()));//urlConn.getInputStream() 代表的就是這個地址的檔案

while ((line = buffer.readLine()) != null) {

sb.append(line);

}

catch (Exception e) {

e.printStackTrace();

finally {

try {

buffer.close();

catch (Exception e) {

e.printStackTrace();

}

}

return sb.toString();

}

 下面講述如何將一個MP3檔案寫入到我們的SDcard裡面

  訪問SDCARD的話,我們首先要獲得SDCARD在我們手機裡面的地址名,由於每個手機的地址明可能是不同的額,於是我們不能把這個地址寫死,android作業系統當中的Environment類的getExternalStorageDirectory() 方法可以提供這個SDCARD的地址。

  一般是/sdcard的形式

  訪問SD卡的許可權:

  android.permission.WRITE_EXTERNAL_STORAGE

  在AndroidManifest.xml   當中進行宣告才行。

  需要使用到一個訪問SDCARD的一個工具類  FileUtils.java  這個類封裝的很好,可以利用。

  下面是獲取手機SDCARD地址的程式碼

private String SDPATH;

public String getSDPATH() {

return SDPATH;

}

public FileUtils() {

//得到當前外部儲存裝置的目錄

// /SDCARD

SDPATH = Environment.getExternalStorageDirectory() + "/";

       //方便增加地址空間

}

  在SDCARD上面建立目錄

/**

/**

 * 在SD卡上建立目錄

 * 

 * @param dirName

 */

public File creatSDDir(String dirName) {

File dir = new File(SDPATH + dirName);

dir.mkdirs();

return dir;

}

File(String fielAddress)  構造方法建立File物件,

mkdirs()  方法執行建立命令

Creates the directory named by this file,

/**

 * 在SD卡上建立檔案

 * 

 * @throws IOException

 */

public File creatSDFile(String fileName) throws IOException {

File file = new File(SDPATH + fileName);

file.createNewFile();

return file;

}

都是javaIO操作

public boolean isFileExist(String fileName){

File file = new File(SDPATH + fileName);

return file.exists();

判斷是否存在此檔案

三個引數  路徑名 檔名  輸入流input

public File write2SDFromInput(String path,String fileName,InputStream input){

File file = null;

OutputStream output = null;

try{

//建立目錄

creatSDDir(path);

//建立檔案

file = creatSDFile(path + fileName);

//建立檔案輸出流

output = new FileOutputStream(file);

byte buffer [] = new byte[4 * 1024];

while((input.read(buffer)) != -1){

output.write(buffer);

}

output.flush();

}

catch(Exception e){

e.printStackTrace();

}

finally{

try{

output.close();

}

catch(Exception e){

e.printStackTrace();

}

}

return file;

}

}

FileOutputStream(File file)
建立一個向指定 File 物件表示的檔案中寫入資料的檔案輸出流。

write

public void write(byte[] b)

將 b.length 個位元組從指定 byte 陣列寫入此檔案輸出流中。 

覆蓋:

引數:

b- 資料。

丟擲:

另請參見:

下面介紹在HttpDownloader 中的的二個方法

這個函式可以下載任意形式的檔案  並且存放在SDCARD的指定目錄當中

/**

 * 該函式返回整形 -1:代表下載檔案出錯 0:代表下載檔案成功 1:代表檔案已經存在

 */

  urlStr  下載檔案的連結     path  存放SDCARD的目錄     fileName  以什麼檔名儲存該檔案 

public int downFile(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);

File resultFile = fileUtils.write2SDFromInput(path,fileName, inputStream);

if (resultFile == null) {

return -1;

}

}

catch (Exception e) {

e.printStackTrace();

return -1;

finally {

try {

inputStream.close();

catch (Exception e) {

e.printStackTrace();

}

}

return 0;

}

用到了封裝函式

/**

 * 根據URL得到輸入流

 * 

 * @param urlStr

 * @return

 * @throws MalformedURLException

 * @throws IOException

 */

public InputStream getInputStreamFromUrl(String urlStr)

throws MalformedURLException, IOException {

url = new URL(urlStr);

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

InputStream inputStream = urlConn.getInputStream();

return inputStream;

}

StringBuffer sb = new StringBuffer();

String line = null;

BufferedReader buffer = null;

try {

// 建立一個URL物件,代表這個地址

url = new URL(urlStr);

// 建立一個Http連線

HttpURLConnection urlConn = (HttpURLConnection) url

.openConnection();

// 使用IO流讀取資料

buffer = new BufferedReader(new InputStreamReader(urlConn

.getInputStream()));//urlConn.getInputStream() 代表的就是這個地址的檔案

其實跟這一段程式碼功能相同 只是

File resultFile = fileUtils.write2SDFromInput(path,fileName, inputStream);

if (resultFile == null) {

return -1;

}

Download.java

package com.example.download;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Download extends Activity {
    /** Called when the activity is first created. */
    private Button downloadTxtButton;
    private Button downloadMp3Button;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        downloadTxtButton = (Button)findViewById(R.id.downloadTxt);
        downloadTxtButton.setOnClickListener(new DownloadTxtListener());
        downloadMp3Button = (Button)findViewById(R.id.downloadMp3);
        downloadMp3Button.setOnClickListener(new DownloadMp3Listener());
    }
    
    class DownloadTxtListener implements OnClickListener{
@Override
public void onClick(View v) {
HttpDownloader httpDownloader = new HttpDownloader();
String lrc = httpDownloader.download("http://192.168.137.1:8080/mywebsite/guoximing.txt");
System.out.println(lrc);
}
    
    }
    class DownloadMp3Listener implements OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
HttpDownloader httpDownloader = new HttpDownloader();
int result = httpDownloader.downFile("http://192.168.137.1:8080/mywebsite/guoxiaoming.txt", "guoximing/", "guoxiaoming.txt");
System.out.println(result);
}
    
    }
    
}


HttpDownloader.java

package com.example.download;
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 {
private URL url = null;
/**
 * 根據URL下載檔案,前提是這個檔案當中的內容是文字,函式的返回值就是檔案當中的內容
 * 1.建立一個URL物件
 * 2.通過URL物件,建立一個HttpURLConnection物件
 * 3.得到InputStram
 * 4.從InputStream當中讀取資料
 * @param urlStr
 * @return
 */
public String download(String urlStr) {
StringBuffer sb = new StringBuffer();
String line = null;
BufferedReader buffer = null;
try {
// 建立一個URL物件,代表這個地址
url = new URL(urlStr);
// 建立一個Http連線
HttpURLConnection urlConn = (HttpURLConnection) url
.openConnection();
// 使用IO流讀取資料
buffer = new BufferedReader(new InputStreamReader(urlConn
.getInputStream()));//urlConn.getInputStream() 代表的就是這個地址的檔案
while ((line = buffer.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
buffer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return sb.toString();
}
/**
 * 該函式返回整形 -1:代表下載檔案出錯 0:代表下載檔案成功 1:代表檔案已經存在
 */
public int downFile(String urlStr, String path, String fileName) {
InputStream inputStream = null;
try {
FileUtils fileUtils = new FileUtils();
if (fileUtils.isFileExist(path + fileName)) {
return 1;
} else {
inputStream = getInputStreamFromUrl(urlStr);
File resultFile = fileUtils.write2SDFromInput(path,fileName, inputStream);
if (resultFile == null) {
return -1;
}
}
} catch (Exception e) {
e.printStackTrace();
return -1;
} finally {
try {
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return 0;
}
/**
 * 根據URL得到輸入流
 * 
 * @param urlStr
 * @return
 * @throws MalformedURLException
 * @throws IOException
 */
public InputStream getInputStreamFromUrl(String urlStr)
throws MalformedURLException, IOException {
url = new URL(urlStr);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConn.getInputStream();
return inputStream;
}
}


FileUtils.java

package com.example.download;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.os.Environment;
public class FileUtils {
private String SDPATH;
public String getSDPATH() {
return SDPATH;
}
public FileUtils() {
//得到當前外部儲存裝置的目錄
// /SDCARD
SDPATH = Environment.getExternalStorageDirectory() + "/";
}
/**
 * 在SD卡上建立檔案
 * 
 * @throws IOException
 */
public File creatSDFile(String fileName) throws IOException {
File file = new File(SDPATH + fileName);
file.createNewFile();
return file;
}
/**
 * 在SD卡上建立目錄
 * 
 * @param dirName
 */
public File creatSDDir(String dirName) {
File dir = new File(SDPATH + dirName);
dir.mkdirs();
return dir;
}
/**
 * 判斷SD卡上的資料夾是否存在
 */
public boolean isFileExist(String fileName){
File file = new File(SDPATH + fileName);
return file.exists();
}
/**
 * 將一個InputStream裡面的資料寫入到SD卡中
 */
public File write2SDFromInput(String path,String fileName,InputStream input){
File file = null;
OutputStream output = null;
try{
//建立目錄
creatSDDir(path);
//建立檔案
file = creatSDFile(path + fileName);
//建立
output = new FileOutputStream(file);
byte buffer [] = new byte[4 * 1024];
while((input.read(buffer)) != -1){
output.write(buffer);
}
output.flush();
}
catch(Exception e){
e.printStackTrace();
}
finally{
try{
output.close();
}
catch(Exception e){
e.printStackTrace();
}
}
return file;
}
}


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
   <Button  
android:id="@+id/downloadTxt"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="下載文字檔案"
    ></Button>
<Button  
android:id="@+id/downloadMp3"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="下載MP3檔案 "
    ></Button>


</LinearLayout>

以上程式是在Android2.3環境下開發的,在高版本的情況下不能再UI執行緒當中訪問網路

這樣就可以了

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class Download extends Activity {
    private Button downloadTxtButton;
    private Button downloadMp3Button;
    @Override
    public void onCreate(Bundle savedInstanceState) {
       
    	
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        downloadTxtButton = (Button)findViewById(R.id.downloadTxt);
        downloadMp3Button = (Button)findViewById(R.id.downloadMp3);
        
        downloadTxtButton.setOnClickListener(new  View.OnClickListener() {
			@Override
			public void onClick(View arg0) {
				new Thread(downloadRun).start(); 
			}
		});
        
        downloadMp3Button.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				new Thread(downloadMp3).start();
				
			}
		});
    }
    
    Runnable downloadRun = new Runnable(){

		@Override
		public void run() {
				HttpDownloader httpDownloader = new HttpDownloader();
				String lrc = httpDownloader.download("http://121.49.87.4:8080/android/11.txt");
				System.out.println(lrc);
		}
    	
    };
    
    Runnable downloadMp3 = new Runnable(){

		@Override
		public void run() {
			// TODO Auto-generated method stub
				HttpDownloader httpDownloader = new HttpDownloader();
				int result = httpDownloader.downFile("http://121.49.87.4:8080/android/11.txt","guoximing/", "guoxiaoming.txt");
				System.out.println(result);
		}
    	
    };    
}