下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
【移動應(yīng)用開發(fā)技術(shù)】Android中怎么利用FTP實現(xiàn)多線程斷點續(xù)傳下載上傳功能
Android中怎么利用FTP實現(xiàn)多線程斷點續(xù)傳下載上傳功能,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面在下將為大家詳細講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。FTP下載原理FTP單線程斷點續(xù)傳FTP和傳統(tǒng)的HTTP協(xié)議有所不同,由于FTP沒有所謂的頭文件,因此我們不能像HTTP那樣通過設(shè)置header向服務(wù)器指定下載區(qū)間。但是FTP協(xié)議提供了一個更好用的命令REST用于從指定位置恢復(fù)任務(wù),同時FTP協(xié)議也提供了一個命令SIZE用于獲取下載的文件大小,有了這兩個命令,F(xiàn)TP斷點續(xù)傳也就沒有什么問題。FTP斷點續(xù)傳的原理和HTTP的斷點續(xù)傳原理差不多,在暫停時記錄文件的停止位置,再次下載時,先讀取記錄的位置,如果位置存在,則通過REST命令告訴服務(wù)器從指定區(qū)間進行下載。FTP多線程斷點續(xù)傳多線程下載的原理和HTTP多線程下載的原理差不多。先獲取文件大小,然后根據(jù)線程數(shù),對整個文件進行分段下載,在任務(wù)停止時,記錄每一條線程的暫停位置,重新開始下載,每一條線程讀取對應(yīng)的下載記錄,然后每一線程從指定位置開始下載。分段下載和HTTP所不同的是,F(xiàn)TP并沒有提供文件區(qū)間的API,因此,F(xiàn)TP在分段下載中,只有起始位置而沒有結(jié)束位置。因此,你需要在指定位置手動停止線程。功能實現(xiàn)本文使用將采用apachecommons-net實現(xiàn)FTP斷點續(xù)傳下載\上傳功能。<br>通過下文的幾步操作,你就能很簡單的實現(xiàn)FTP斷點續(xù)傳。登錄FTP協(xié)議和HTTP協(xié)議有所不同,使用FTP進行下載時,你需要進行登錄操作。當(dāng)然,如果你服務(wù)器沒有登錄功能,你可以忽略登錄操作。FTPClient
client
=
new
FTPClient();
client.connect(serverIp,
port);
//連接到FTP服務(wù)器
client.login(userName,
passsword);通過上面三行代碼,就可以很簡單的登錄到FTP服務(wù)器上。在進行登錄后,還需要驗證是否登錄成功int
reply
=
client.getReplyCode();
if
(!FTPReply.isPositiveCompletion(reply))
{
client.disconnect();
Log.d(TAG,
"無法連接到ftp服務(wù)器,錯誤碼為:"
+
reply);
return;
}由于FTP協(xié)議中,連接成功的狀態(tài)有多個,因此需要通過FTPReply.isPositiveCompletion(reply)用于驗證是否成功連接到FTP服務(wù)器。文件信息獲取在連接到FTP服務(wù)器后,就需要開始獲取下載最重要的幾個參數(shù)(文件長度、文件名)。客戶端可以通過client.listFiles(remotePath)獲取FTP服務(wù)器上該路徑的文件列表。如果路徑是文件,只會返回一個長度為1的數(shù)組。如果該路徑為文件夾,則會返回該文件夾下對應(yīng)的所有文件。String
remotePath
=
"/upload/qjnn.apk";
//FTP服務(wù)器上文件路徑
FTPFile[]
files
=
client.listFiles(remotePath);
FTPFile
file
=
files[0];
//文件信息
long
size
=
file.getSize();
String
fileaName
=
file.getName();如果你的文件為英文名,并且路徑中沒有中文,那么通過上述代碼,便可以獲取到正確的文件信息。但如果FTP上的服務(wù)器上的文件名有中文或路徑有中文,那么上述代碼,你將獲取不到正確的文件信息。正確的寫法由于FTP服務(wù)器默認的編碼是ISO-8859-1,因此,客戶端在獲取文件信息時需要請求服務(wù)器使用UTF-8編碼(如果服務(wù)器支持的話),如果服務(wù)器不支持開啟UTF-8編碼,那么客戶端需要指定字符串編碼格式客戶端在請求remotePath路徑、獲取文件名時,都需要對路徑進行編碼轉(zhuǎn)換處理。String
remotePath
=
"/upload/qjnn.apk";
//FTP服務(wù)器上文件路徑
String
charSet
=
"UTF-8";
if
(!FTPReply.isPositiveCompletion(client.sendCommand("OPTS
UTF8",
"ON")))
{
//向服務(wù)器請求使用"UTF-8"編碼
charSet
=
"GBK";
}
FTPFile[]
files
=
client.listFiles(new
String(remotePath.getBytes(charSet),
"ISO-8859-1"));
//對remotePath進行編碼轉(zhuǎn)換
FTPFile
file
=
files[0];
//文件信息
long
size
=
file.getSize();
String
fileaName
=
new
String(fileName.getBytes(),
Charset.forName(charSet));通過以上代碼,便可以獲取到正確的文件信息。文件下載配置每條線程的下載區(qū)間long
fileLength
=
mEntity.getFileSize();
Properties
pro
=
CommonUtil.loadConfig(mConfigFile);
int
blockSize
=
(int)
(fileLength
/
mThreadNum);
int[]
recordL
=
new
int[mThreadNum];
for
(int
i
=
0;
i
<
mThreadNum;
i++)
{
recordL[i]
=
-1;
}
int
rl
=
0;
for
(int
i
=
0;
i
<
mThreadNum;
i++)
{
long
startL
=
i
*
blockSize,
endL
=
(i
+
1)
*
blockSize;
Object
state
=
pro.getProperty(mTempFile.getName()
+
"_state_"
+
i);
if
(state
!=
null
&&
Integer.parseInt(state
+
"")
==
1)
{
//該線程已經(jīng)完成
if
(resumeRecordLocation(i,
startL,
endL))
return;
continue;
}
//分配下載位置
Object
record
=
pro.getProperty(fileName
+
"_record_"
+
i);
//如果有記錄,則恢復(fù)下載
if
(record
!=
null
&&
Long.parseLong(record
+
"")
>=
0)
{
Long
r
=
Long.parseLong(record
+
"");
mConstance.CURRENT_LOCATION
+=
r
-
startL;
Log.d(TAG,
"任務(wù)【"
+
mEntity.getFileName()
+
"】線程__"
+
i
+
"__恢復(fù)下載");
startL
=
r;
recordL[rl]
=
i;
rl++;
}
else
{
recordL[rl]
=
i;
rl++;
}
//最后一個線程的結(jié)束位置即為文件的總長度
if
(i
==
(mThreadNum
-
1))
endL
=
fileLength;
//創(chuàng)建分段線程
AbsThreadTask
task
=
createSingThreadTask(i,
startL,
endL,
fileLength);
if
(task
==
null)
return;
mTask.put(i,
task);
}
startSingleTask(recordL);在上面的代碼中,主要做了兩步操作:在文件下載前,先從本地文件中讀取當(dāng)前下載的每一條線程的下載情況如果下載記錄存在,從記錄位置開始下載,如果記錄不存在,則重新開始下載FTP分段線程區(qū)間自動停止由于FTP協(xié)議沒有區(qū)間下載的原因,為了讓線程只下載特定區(qū)間的內(nèi)容,需要客戶端在單條線程累計讀的數(shù)據(jù)長度已經(jīng)超過了所分配的區(qū)間長度的時候,停止該條線程。
client.enterLocalPassiveMode();
//設(shè)置被動模式
client.setFileType(FTP.BINARY_FILE_TYPE);
//設(shè)置文件傳輸模式
client.setRestartOffset(mConfig.START_LOCATION);
//設(shè)置恢復(fù)下載的位置
client.allocate(mBufSize);
is
=
client.retrieveFileStream(new
String(remotePath.getBytes(charSet),
SERVER_CHARSET));
//發(fā)送第二次指令時,還需要再做一次判斷
reply
=
client.getReplyCode();
if
(!FTPReply.isPositivePreliminary(reply))
{
client.disconnect();
fail(mChildCurrentLocation,
"獲取文件信息錯誤,錯誤碼為:"
+
reply,
null);
return;
}
file
=
new
BufferedRandomAccessFile(mConfig.TEMP_FILE,
"rwd",
mBufSize);
file.seek(mConfig.START_LOCATION);
byte[]
buffer
=
new
byte[mBufSize];
int
len;
while
((len
=
is.read(buffer))
!=
-1)
{
//如果該條線程讀取的數(shù)據(jù)長度大于所分配的區(qū)間長度,則只能讀到區(qū)間的最大長度
if
(mChildCurrentLocation
+
len
>=
mConfig.END_LOCATION)
{
len
=
(int)
(mConfig.END_LOCATION
-
mChildCurrentLocation);
file.write(buffer,
0,
len);
progress(len);
break;
}
else
{
file.write(buffer,
0,
len);
progress(len);
}
}這里還有幾個坑需要處理一下:對于FTP客戶端來說,一般需要設(shè)置被動模式,被動模式和
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 商業(yè)服務(wù)租賃合同轉(zhuǎn)讓樣本
- 幼兒園主班教師聘用合同
- 網(wǎng)絡(luò)安全索賠協(xié)議
- 沿海工程物探施工合同
- 總代理特別物流協(xié)議
- 宗教場所保安員聘用協(xié)議
- 投標(biāo)聯(lián)合體終止協(xié)議
- 旅游服務(wù)合同備案辦法
- 家政服務(wù)招投標(biāo)合同管理要點
- 學(xué)校大門鋼架雨棚安裝協(xié)議
- 四川省涼山州西昌市2023-2024學(xué)年四年級上學(xué)期期末數(shù)學(xué)試卷
- 康復(fù)護理的歷史發(fā)展
- 煙花爆竹從業(yè)人員安全培訓(xùn)試題
- 電梯使用現(xiàn)場類隱患專項排查清單
- 一例下肢靜脈潰瘍患者的個案護理論文
- 危巖穩(wěn)定性計算表格-滑移式-傾倒式-墜落式-完整版
- 直播運營團隊組織架構(gòu)及崗位職責(zé)解析
- 肝膽外科運用PDCA循環(huán)縮短三四類手術(shù)患者術(shù)后留置導(dǎo)尿的時間
- JCT640-2010 頂進施工法用鋼筋混凝土排水管
- 注塑車間平面規(guī)劃圖OK
- 商戶洽談記錄表
評論
0/150
提交評論