Android 實現斷點上傳文件
使用Socket TCP/IP方式進行文件上傳
代碼:
package com.example.androidseekuploadfile;
import java.io.File;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.io.RandomAccessFile;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.example.androidseekuploadfile.db.UploadLogService;
import com.example.androidseekuploadfile.tools.StreamTool;
/**
* android實現斷點上傳文件
* @author miaowei
*
*/
public class MainActivity extends Activity {
/**
* 文件名
*/
private EditText filenameEditText;
/**
* 上傳結果
*/
private TextView resultView;
/**
* 等待框
*/
private ProgressBar uploadBar;
/**
* 上傳服務
*/
private UploadLogService logService;
/**
* 是否開啓上傳
*/
private boolean start = true;
/**
* 上傳
*/
private Button btn_upload;
/**
* 暫停
*/
private Button btn_stop;
/**
* 本地測試
*/
String pathString = Environment.getExternalStorageDirectory().getAbsolutePath();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
logService = new UploadLogService(this);
filenameEditText = (EditText)this.findViewById(R.id.filename);
uploadBar = (ProgressBar) this.findViewById(R.id.uploadbar);
resultView = (TextView)this.findViewById(R.id.result);
btn_upload =(Button)this.findViewById(R.id.btn_upload);
btn_stop =(Button)this.findViewById(R.id.btn_stop);
btn_upload.setOnClickListener(onClickListener);
btn_stop.setOnClickListener(onClickListener);
}
/**
* 事件處理
*/
private OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_upload://上傳
start = true;
String filename = filenameEditText.getText().toString();
//判斷SDCard是否存在
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//取得SDCard的目錄
//File uploadFile = new File(Environment.getExternalStorageDirectory(), filename);
//本地測試使用
File uploadFile = new File(pathString+"/Android/data/com.mapbar.info.collection/files/cache.zip");
if(uploadFile.exists()){
//開始上傳文件
uploadFile(uploadFile);
}else{
Toast.makeText(MainActivity.this,"文件不存在",Toast.LENGTH_SHORT).show();
}
}else{
Toast.makeText(MainActivity.this,"未檢測到SD卡", Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_stop://暫停
start = false;
break;
default:
break;
}
}
};
/**
* 上傳文件
* 啓動一個線程,使用Handler來避免UI線程ANR錯誤
* @param uploadFile
*/
private void uploadFile(final File uploadFile) {
new Thread(new Runnable() {
@Override
public void run() {
try {
//設置長傳文件的最大刻度
uploadBar.setMax((int)uploadFile.length());
//判斷文件是否已有上傳記錄
String souceid = logService.getBindId(uploadFile);
//構造拼接協議
String head = "Content-Length="+ uploadFile.length() + ";filename="+ uploadFile.getName() + ";sourceid="+
(souceid==null? "" : souceid)+"\r\n";
//通過Socket取得輸出流
//測試使用,具體自配
Socket socket = new Socket("192.168.1.10",8080);
OutputStream outStream = socket.getOutputStream();
outStream.write(head.getBytes());
PushbackInputStream inStream = new PushbackInputStream(socket.getInputStream());
//獲取到字符流的id與位置
String response = StreamTool.readLine(inStream);
String[] items = response.split(";");
String responseid = items[0].substring(items[0].indexOf("=")+1);
String position = items[1].substring(items[1].indexOf("=")+1);
//代表原來沒有上傳過此文件,往數據庫添加一條綁定記錄
if(souceid==null){
logService.save(responseid, uploadFile);
}
RandomAccessFile fileOutStream = new RandomAccessFile(uploadFile, "r");
fileOutStream.seek(Integer.valueOf(position));
byte[] buffer = new byte[1024];
int len = -1;
//初始化長傳的數據長度
int length = Integer.valueOf(position);
while(start&&(len = fileOutStream.read(buffer)) != -1){
outStream.write(buffer, 0, len);
//設置長傳數據長度
length += len;
Message msg = new Message();
msg.getData().putInt("size", length);
mHandler.sendMessage(msg);
}
fileOutStream.close();
outStream.close();
inStream.close();
socket.close();
//判斷上傳完則刪除數據
if(length==uploadFile.length()){
logService.delete(uploadFile);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
/**
* 使用Handler給創建他的線程發送消息
* UI更新
*/
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
//獲得上傳長度的進度
int length = msg.getData().getInt("size");
uploadBar.setProgress(length);
float num = (float)uploadBar.getProgress()/(float)uploadBar.getMax();
//設置顯示結果
int result = (int)(num * 100);
resultView.setText(result+ "%");
//上傳成功
if(uploadBar.getProgress()==uploadBar.getMax()){
Toast.makeText(MainActivity.this, "上傳成功", Toast.LENGTH_SHORT).show();
}
}
};
}
package com.example.androidseekuploadfile.db;
import java.io.File;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
/**
* 操作數據庫
* @author miaowei
*
*/
public class UploadLogService {
private DBOpenHelper dbOpenHelper;
public UploadLogService(Context context){
this.dbOpenHelper = new DBOpenHelper(context);
}
/**
* 保存上傳文件斷點數據
* @param sourceid 標識ID
* @param uploadFile 文件
*/
public void save(String sourceid, File uploadFile){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("insert into uploadlog(uploadfilepath, sourceid) values(?,?)",
new Object[]{uploadFile.getAbsolutePath(),sourceid});
}
/**
* 文件上傳完成,刪除上傳文件斷點數據
* @param uploadFile
*/
public void delete(File uploadFile){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
db.execSQL("delete from uploadlog where uploadfilepath=?", new Object[]{uploadFile.getAbsolutePath()});
}
/**
* 根據文件的上傳路徑得到綁定的id
* @param uploadFile
* @return
*/
public String getBindId(File uploadFile){
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select sourceid from uploadlog where uploadfilepath=?",
new String[]{uploadFile.getAbsolutePath()});
if(cursor.moveToFirst()){
return cursor.getString(0);
}
return null;
}
}
package com.example.androidseekuploadfile.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* 數據庫幫助類
* @author miaowei
*
*/
public class DBOpenHelper extends SQLiteOpenHelper {
/**
* 文件名
*/
private String uploadfilepath;
/**
* 記錄文件標識
*/
private String sourceid;
public DBOpenHelper(Context context) {
super(context, "upload.db", null, 1);
}
/**
* 創建數據庫
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE uploadlog (_id integer primary key autoincrement, uploadfilepath varchar(100), sourceid varchar(10))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS uploadlog");
onCreate(db);
}
}
分享:http://blog.csdn.net/shimiso/article/details/8529633
具體操作見附件源碼: