您的位置:首页 > 移动开发 > Android开发

Android神奇编程之通过SOCKET协议实现断点续传上传

2012-09-13 15:59 615 查看
通过SOCKET协议实现断点续传上传

packagecn.itcast.net.server;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileOutputStream;

importjava.io.IOException;

importjava.io.OutputStream;

importjava.io.PushbackInputStream;

importjava.io.RandomAccessFile;

importjava.net.ServerSocket;

importjava.net.Socket;

importjava.text.SimpleDateFormat;

importjava.util.Date;

importjava.util.HashMap;

importjava.util.Map;

importjava.util.Properties;

importjava.util.concurrent.ExecutorService;

importjava.util.concurrent.Executors;

importcn.itcast.utils.StreamTool;

publicclass FileServer {

private ExecutorService executorService;//线程池

private int port;//监听端口

private boolean quit = false;//退出

private ServerSocket server;

private Map<Long, FileLog> datas = newHashMap<Long, FileLog>();//存放断点数据

public FileServer(int port){

this.port = port;

//创建线程池,池中具有(cpu个数*50)条线程

//创建固定数量的线程池 获取cpu的个数
100个并发链接


executorService =Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 50);

}

/**

*退出

*/

public void quit(){

this.quit = true;

try {

server.close();

} catch (IOException e) {

}

}

/**

*启动服务

*@throws Exception

*/

public void start() throws Exception{

//建立服务器端口事例

server = new ServerSocket(port);

while(!quit){

try {

//接受客户端链接

Socket socket = server.accept();

//为支持多用户并发访问,采用线程池管理每一个用户的连接请求

executorService.execute(new SocketTask(socket));

} catch (Exception e) {

e.printStackTrace();

}

}

}

private final class SocketTask implementsRunnable{

private Socket socket = null;

public SocketTask(Socket socket) {

this.socket = socket;

}

@Override

public void run() {

try {

System.out.println("acceptedconnection "+ socket.getInetAddress()+ ":"+ socket.getPort());

PushbackInputStreaminStream = new PushbackInputStream(socket.getInputStream());

//得到客户端发来的第一行协议数据:Content-Length=143253434;filename=xxx.3gp;sourceid=

//如果用户初次上传文件,sourceid的值为空。

String head =StreamTool.readLine(inStream);

System.out.println(head);

if(head!=null){

//下面从协议数据中提取各项参数值

String[]items = head.split(";");

Stringfilelength = items[0].substring(items[0].indexOf("=")+1);

Stringfilename = items[1].substring(items[1].indexOf("=")+1);

Stringsourceid = items[2].substring(items[2].indexOf("=")+1);

long id =System.currentTimeMillis();//生产资源id,如果需要唯一性,可以采用UUID

FileLog log =null;

if(sourceid!=null&& !"".equals(sourceid)){

id =Long.valueOf(sourceid);

log =find(id);//查找上传的文件是否存在上传记录

}

File file =null;

int position= 0;

if(log==null){//如果上传的文件不存在上传记录,为文件添加跟踪记录

Stringpath = new SimpleDateFormat("yyyy/MM/dd/HH/mm").format(new Date());

Filedir = new File("file/"+ path);

if(!dir.exists())dir.mkdirs();

file =new File(dir, filename);

if(file.exists()){//如果上传的文件发生重名,然后进行改名

filename= filename.substring(0, filename.indexOf(".")-1)+dir.listFiles().length+ filename.substring(filename.indexOf("."));

file= new File(dir, filename);

}

save(id,file);

}else{//如果上传的文件存在上传记录,读取上次的断点位置

file =new File(log.getPath());//从上传记录中得到文件的路径

if(file.exists()){

FilelogFile = new File(file.getParentFile(), file.getName()+".log");

if(logFile.exists()){

Propertiesproperties = new Properties();

properties.load(newFileInputStream(logFile));

position= Integer.valueOf(properties.getProperty("length"));//读取断点位置

}

}

}

OutputStreamoutStream = socket.getOutputStream();

Stringresponse = "sourceid="+ id+ ";position="+ position+"\r\n";

//服务器收到客户端的请求信息后,给客户端返回响应信息:sourceid=1274773833264;position=0

//sourceid由服务器端生成,唯一标识上传的文件,position指示客户端从文件的什么位置开始上传

outStream.write(response.getBytes());

RandomAccessFilefileOutStream = new RandomAccessFile(file, "rwd");

if(position==0)fileOutStream.setLength(Integer.valueOf(filelength));//设置文件长度

fileOutStream.seek(position);//移动文件指定的位置开始写入数据

byte[] buffer= new byte[1024];

int len = -1;

int length =position;

while((len=inStream.read(buffer)) != -1){//从输入流中读取数据写入到文件中

fileOutStream.write(buffer,0, len);

length+= len;

Propertiesproperties = new Properties();

properties.put("length",String.valueOf(length));

FileOutputStreamlogFile = new FileOutputStream(new File(file.getParentFile(),file.getName()+".log"));

properties.store(logFile,null);//实时记录文件的最后保存位置

logFile.close();

}

if(length==fileOutStream.length())delete(id);

fileOutStream.close();

inStream.close();

outStream.close();

file = null;

}

} catch (Exception e) {

e.printStackTrace();

}finally{

try {

if(socket!=null &&!socket.isClosed()) socket.close();

} catch (IOException e) {}

}

}

}

public FileLog find(Long sourceid){

return datas.get(sourceid);

}

//保存上传记录

public void save(Long id, File saveFile){

//日后可以改成通过数据库存放

datas.put(id, new FileLog(id,saveFile.getAbsolutePath()));

}

//当文件上传完毕,删除记录

public void delete(long sourceid){

if(datas.containsKey(sourceid))datas.remove(sourceid);

}

private class FileLog{

private Long id;

private String path;

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public String getPath() {

return path;

}

public void setPath(String path) {

this.path = path;

}

public FileLog(Long id, Stringpath) {

this.id = id;

this.path = path;

}

}

}

packagecn.itcast.net.client;

importjava.io.ByteArrayOutputStream;

importjava.io.File;

importjava.io.InputStream;

importjava.io.OutputStream;

importjava.io.PushbackInputStream;

importjava.io.RandomAccessFile;

importjava.net.Socket;

importcn.itcast.utils.StreamTool;

publicclass SocketClient {

/**

*@param args

*/

public static void main(String[] args) {

try {

// Socketsocket = new Socket("127.0.0.1", 7878);

Socket socket = newSocket("127.0.0.1", 7878);

OutputStream outStream =socket.getOutputStream();

String filename ="QQWubiSetup.exe";

File file = new File(filename);

String head ="Content-Length="+ file.length() + ";filename="+ filename +";sourceid=\r\n";

outStream.write(head.getBytes());

PushbackInputStream inStream = newPushbackInputStream(socket.getInputStream());

String response =StreamTool.readLine(inStream);

System.out.println(response);

String[] items =response.split(";");

String position =items[1].substring(items[1].indexOf("=")+1);

RandomAccessFile fileOutStream= new RandomAccessFile(file, "r");

fileOutStream.seek(Integer.valueOf(position));

byte[] buffer = newbyte[1024];

int len = -1;

int i = 0;

while( (len =fileOutStream.read(buffer)) != -1){

outStream.write(buffer,0, len);

i++;

//if(i==10) break;

}

fileOutStream.close();

outStream.close();

inStream.close();

socket.close();

} catch (Exception e) {

e.printStackTrace();

}

}

/**

*读取流

* @param inStream

* @return字节数组

* @throws Exception

*/

public static byte[]readStream(InputStream inStream) throws Exception{

ByteArrayOutputStreamoutSteam = new ByteArrayOutputStream();

byte[] buffer = newbyte[1024];

int len = -1;

while((len=inStream.read(buffer)) != -1){

outSteam.write(buffer,0, len);

}

outSteam.close();

inStream.close();

returnoutSteam.toByteArray();

}

}

视频上传package cn.itcast.upload;

importjava.io.File;

importjava.io.OutputStream;

importjava.io.PushbackInputStream;

importjava.io.RandomAccessFile;

importjava.net.Socket;

importcn.itcast.service.UploadLogService;

importcn.itcast.utils.StreamTool;

importandroid.app.Activity;

importandroid.os.Bundle;

importandroid.os.Environment;

importandroid.os.Handler;

importandroid.os.Message;

importandroid.view.View;

importandroid.widget.Button;

importandroid.widget.EditText;

importandroid.widget.ProgressBar;

importandroid.widget.TextView;

importandroid.widget.Toast;

publicclass MainActivity extends Activity {

private EditText filenameText;

private TextView resultView;

private ProgressBar uploadbar;

private UploadLogService service;

private Handler handler = new Handler(){

@Override

public void handleMessage(Messagemsg) {

uploadbar.setProgress(msg.getData().getInt("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,R.string.success, 1).show();

}

}

};

@Override

public void onCreate(BundlesavedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

service = new UploadLogService(this);

filenameText =(EditText)findViewById(R.id.filename);

resultView =(TextView)findViewById(R.id.result);

uploadbar =(ProgressBar)findViewById(R.id.uploadbar);

Button button =(Button)findViewById(R.id.button);

button.setOnClickListener(newView.OnClickListener() {

@Override

public void onClick(View v){

String filename =filenameText.getText().toString();

if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){

File file =new File(Environment.getExternalStorageDirectory(), filename);

if(file.exists()){

uploadbar.setMax((int)file.length());

uploadFile(file);

}else{

Toast.makeText(MainActivity.this,R.string.notexsit, 1).show();

}

}else{

Toast.makeText(MainActivity.this,R.string.sdcarderror, 1).show();

}

}

});

}

private void uploadFile(final File file){

new Thread(new Runnable() {

@Override

public void run() {

try {

Stringsourceid = service.getBindId(file);

Socket socket= new Socket("192.168.1.10", 7878);

OutputStream outStream =socket.getOutputStream();

String head ="Content-Length="+ file.length() + ";filename="+file.getName()

+";sourceid="+(sourceid!=null ? sourceid :"")+"\r\n";

outStream.write(head.getBytes());

PushbackInputStream inStream = newPushbackInputStream(socket.getInputStream());

Stringresponse = StreamTool.readLine(inStream);

String[] items =response.split(";");

StringresponseSourceid = items[0].substring(items[0].indexOf("=")+1);

Stringposition = items[1].substring(items[1].indexOf("=")+1);

if(sourceid==null){//如果是第一次上传文件,在数据库中存在该文件所绑定的资源id

service.save(responseSourceid,file);

}

RandomAccessFilefileOutStream = new RandomAccessFile(file, "r");

fileOutStream.seek(Integer.valueOf(position));

byte[] buffer= new byte[1024];

int len = -1;

int length =Integer.valueOf(position);

while( (len =fileOutStream.read(buffer)) != -1){

outStream.write(buffer,0, len);

length+= len;//累加已经上传的数据长度

Messagemsg = new Message();

msg.getData().putInt("length",length);

handler.sendMessage(msg);

}

if(length ==file.length()) service.delete(file);

fileOutStream.close();

outStream.close();

inStream.close();

socket.close();

} catch (Exception e) {

Toast.makeText(MainActivity.this,R.string.error, 1).show();

}

}

}).start();

}

}

packagecn.itcast.utils;

importjava.io.ByteArrayOutputStream;

importjava.io.File;

importjava.io.FileOutputStream;

importjava.io.IOException;

importjava.io.InputStream;

importjava.io.PushbackInputStream;

publicclass StreamTool {

public static void save(File file, byte[]data) throws Exception {

FileOutputStream outStream = newFileOutputStream(file);

outStream.write(data);

outStream.close();

}

public static StringreadLine(PushbackInputStream in) throws IOException {

char buf[] = new char[128];

int room = buf.length;

int offset = 0;

int c;

loop: while (true) {

switch (c =in.read()) {

case -1:

case '\n':

breakloop;

case '\r':

int c2= in.read();

if((c2 != '\n') && (c2 != -1)) in.unread(c2);

breakloop;

default:

if(--room < 0) {

char[]lineBuffer = buf;

buf = new char[offset + 128];

room = buf.length - offset - 1;

System.arraycopy(lineBuffer, 0, buf, 0,offset);

}

buf[offset++]= (char) c;

break;

}

}

if ((c == -1) &&(offset == 0)) return null;

returnString.copyValueOf(buf, 0, offset);

}

/**

*读取流

* @param inStream

* @return字节数组

* @throws Exception

*/

public static byte[]readStream(InputStream inStream) throws Exception{

ByteArrayOutputStreamoutSteam = new ByteArrayOutputStream();

byte[] buffer = newbyte[1024];

int len = -1;

while((len=inStream.read(buffer)) != -1){

outSteam.write(buffer,0, len);

}

outSteam.close();

inStream.close();

returnoutSteam.toByteArray();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: