使用xUtils3和RandomAccessFile來實現檔案的分片上傳
首先,想使用xUtils3需要先做好相應的配置,這裡就不詳細說了,詳細http://blog.csdn.net/a1002450926/article/details/50341173
在這裡我自己封裝了一個上傳檔案的方法,如下:
//檔案上傳
public static <T> Cancelable UploadFile(String url,String jsonString,byte[] buffer,CommonCallback<T> callback){
RequestParams params=new RequestParams(url);
if(null!=jsonString){
params.addBodyParameter("info",jsonString,"application/octet-stream","blob");
params.addBodyParameter("file",buffer,"application/octet-stream","blob");
}
params.setMultipart(true);
Cancelable cancelable=x.http().post(params, callback);
return cancelable;
}
在這裡要說明幾個重要引數:
jsonString:這個引數是在我們使用表單上傳檔案的時候需要傳給伺服器的json串
buffer:這個引數是我們在進行檔案上傳的時候檔案的一片位元組流
其它都是按照請求協議自己拼接的,用抓包工具抓包一看便知
要想實現檔案的分片上傳,本文用到的思想是遞迴的,先上程式碼:
int offset = 0;
int readLength;
private void uploadFile(final UploadInfo uploadInfo) {
String absolutePath = uploadInfo.getFile().getAbsolutePath();
long length = uploadInfo.getFile().length();
RandomAccessFile randomAccessFile = null;
byte[] readBuffer = new byte[4 * 1024 * 1024];
JSONObject jsonObject = new JSONObject();
try {
randomAccessFile = new RandomAccessFile(absolutePath, "r");
randomAccessFile.seek(offset);
readLength = randomAccessFile.read(readBuffer, 0, 4 * 1024 * 1024);
long filePointer = randomAccessFile.getFilePointer();
if (readLength < 4 * 1024 * 1024) {
byte[] readBuffer2 = new byte[readLength];
randomAccessFile.seek(offset);
readLength = randomAccessFile.read(readBuffer2, 0, readLength);
randomAccessFile.close();
jsonObject.put("file_size", uploadInfo.getFileSize());
jsonObject.put("file_offset", offset);
jsonObject.put("file_md5", MD5Utils.getFileMD5(uploadInfo.getFile()));
jsonObject.put("file_path", "/b/" + uploadInfo.getName());
jsonObject.put("device", 0);
if (readLength != -1) {
HttpUtils.UploadFile(GlobalConstants.SERVER_ORIGIN + GlobalConstants.SERVER_UPLOAD, jsonObject.toString(), readBuffer2, new MyProgressCallBack<String>() {
@Override
public void onLoading(long total, long current, boolean isDownloading) {
super.onLoading(total, current, isDownloading);
}
@Override
public void onSuccess(String result) {
super.onSuccess(result);
offset = offset + readLength;
if (readLength > 0 && readLength <= (4 * 1024 * 1024)) {
uploadFile(uploadInfo);
}
}
});
}
} else {
randomAccessFile.close();
jsonObject.put("file_size", uploadInfo.getFileSize());
jsonObject.put("file_offset", offset);
jsonObject.put("file_md5", MD5Utils.getFileMD5(uploadInfo.getFile()));
jsonObject.put("file_path", "/b/" + uploadInfo.getName());
jsonObject.put("device", 0);
if (readLength != -1) {
HttpUtils.UploadFile(GlobalConstants.SERVER_ORIGIN + GlobalConstants.SERVER_UPLOAD, jsonObject.toString(), readBuffer, new MyProgressCallBack<String>() {
@Override
public void onLoading(long total, long current, boolean isDownloading) {
super.onLoading(total, current, isDownloading);
}
@Override
public void onSuccess(String result) {
super.onSuccess(result);
offset = offset + readLength;
if (readLength > 0 && readLength <= (4 * 1024 * 1024)) {
uploadFile(uploadInfo);
}
}
});
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
這裡重點解釋一下RandomAccessFile的使用,就按照自己的理解來說明一下:
1. 開啟檔案 randomAccessFile = new RandomAccessFile(absolutePath, "r");
兩個引數:一個是要上傳的檔案的絕對路徑,另一個引數是對檔案要做的操作,這裡做制度操作
2. 讀檔案 readLength = randomAccessFile.read(readBuffer, 0, 4 * 1024 * 1024);
我這裡是將檔案按4M大小的一片來讀出來的,其中三個引數分表代表:讀出來的位元組流存放的地方,從什麼位置開始讀,讀多少
定義的位元組流的大小必須和讀的長度的值相同,需要注意的一點是,當下一次讀檔案的時候,會接著上次的位置繼續讀,也就是說檔案的指標位置在檔案被讀了之後自動定位到此時被讀的大小的位置之後,要想改變讀取檔案的位置,可以使用 randomAccessFile.seek(offset);這個方法可以將指標指向你要讀的檔案的位置
3. 注意讀檔案的最後一片的時候可能會跟之前設定的readBuffer大小不同,這時候需要重新定義readBuffer的大小,同時將讀檔案的位置設定到最後一片的開始位置,具體的上面程式碼中都有寫到
4.當檔案被讀取完成之後,readLength 的值是-1,可以用這個來判斷檔案是否被讀取完畢