首先,想使用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,可以用这个来判断文件是否被读取完毕