android中利用socket上传文件

jopen 8年前

  • android客户端

  • UploadActivity.java    package com.android.upload;  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.android.service.UploadLogService;    import com.android.socket.utils.StreamTool;        public class UploadActivity extends Activity {        private EditText filenameText;        private TextView resulView;        private ProgressBar uploadbar;        private UploadLogService logService;        private boolean start=true;      private Handler handler = 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);                resulView.setText(result+ "%");                if(uploadbar.getProgress()==uploadbar.getMax()){                    Toast.makeText(UploadActivity.this, R.string.success, 1).show();                }            }        };                @Override        public void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.main);                        logService = new UploadLogService(this);            filenameText = (EditText)this.findViewById(R.id.filename);            uploadbar = (ProgressBar) this.findViewById(R.id.uploadbar);            resulView = (TextView)this.findViewById(R.id.result);            Button button =(Button)this.findViewById(R.id.button);            Button button1 =(Button)this.findViewById(R.id.stop);           button1 .setOnClickListener(new OnClickListener() {          @Override     public void onClick(View v) {      start=false;           }    });          button.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                 start=true;                  String filename = filenameText.getText().toString();                    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){                        File uploadFile = new File(Environment.getExternalStorageDirectory(), filename);                        if(uploadFile.exists()){                            uploadFile(uploadFile);                        }else{                            Toast.makeText(UploadActivity.this, R.string.filenotexsit, 1).show();                        }                    }else{                        Toast.makeText(UploadActivity.this, R.string.sdcarderror, 1).show();                    }                }            });        }        /**        * 上传文件        * @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 = new Socket("192.168.1.78",7878);                        OutputStream outStream = socket.getOutputStream();                        outStream.write(head.getBytes());                                                PushbackInputStream inStream = new PushbackInputStream(socket.getInputStream());                            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);                            handler.sendMessage(msg);                        }                        fileOutStream.close();                        outStream.close();                        inStream.close();                        socket.close();                        if(length==uploadFile.length()) logService.delete(uploadFile);                    } catch (Exception e) {                        e.printStackTrace();                    }                }            }).start();        }    }    StreamTool.java    package com.android.socket.utils;    import java.io.ByteArrayOutputStream;  import java.io.File;  import java.io.FileOutputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.PushbackInputStream;    public class StreamTool {        public static void save(File file, byte[] data) throws Exception {     FileOutputStream outStream = new FileOutputStream(file);     outStream.write(data);     outStream.close();    }        public static String readLine(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':        break loop;       case '\r':        int c2 = in.read();        if ((c2 != '\n') && (c2 != -1)) in.unread(c2);        break loop;       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;     return String.copyValueOf(buf, 0, offset);   }       /**   * 读取流   * @param inStream   * @return 字节数组   * @throws Exception   */   public static byte[] readStream(InputStream inStream) throws Exception{     ByteArrayOutputStream outSteam = new ByteArrayOutputStream();     byte[] buffer = new byte[1024];     int len = -1;     while( (len=inStream.read(buffer)) != -1){      outSteam.write(buffer, 0, len);     }     outSteam.close();     inStream.close();     return outSteam.toByteArray();   }  }    UploadLogService.java    package com.android.service;    import java.io.File;    import android.content.Context;  import android.database.Cursor;  import android.database.sqlite.SQLiteDatabase;    public class UploadLogService {   private DBOpenHelper dbOpenHelper;      public UploadLogService(Context context){    this.dbOpenHelper = new DBOpenHelper(context);   }      public void save(String sourceid, File uploadFile){    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();    db.execSQL("insert into uploadlog(uploadfilepath, sourceid) values(?,?)",      new Object[]{uploadFile.getAbsolutePath(),sourceid});   }      public void delete(File uploadFile){    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();    db.execSQL("delete from uploadlog where uploadfilepath=?", new Object[]{uploadFile.getAbsolutePath()});   }      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;   }  }    DBOpenHelper.java    package com.android.service;    import android.content.Context;  import android.database.sqlite.SQLiteDatabase;  import android.database.sqlite.SQLiteOpenHelper;    public class DBOpenHelper extends SQLiteOpenHelper {     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);     }    }    main.xml    <?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:orientation="vertical"      android:layout_width="fill_parent"      android:layout_height="fill_parent"      >  <TextView        android:layout_width="fill_parent"       android:layout_height="wrap_content"       android:text="@string/filename"      />            <EditText         android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:text="022.jpg"       android:id="@+id/filename"       />             <Button         android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/button"       android:id="@+id/button"       />      <Button         android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="暂停"       android:id="@+id/stop"       />   <ProgressBar         android:layout_width="fill_parent"         android:layout_height="20px"        style="?android:attr/progressBarStyleHorizontal"        android:id="@+id/uploadbar"        />    <TextView         android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:gravity="center"       android:id="@+id/result"       />   </LinearLayout>    AndroidManifest.xml    <?xml version="1.0" encoding="utf-8"?>  <manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="com.android.upload"      android:versionCode="1"      android:versionName="1.0" >        <uses-sdk android:minSdkVersion="8" />        <application          android:icon="@drawable/ic_launcher"          android:label="@string/app_name" >          <activity              android:name=".UploadActivity"              android:label="@string/app_name" >              <intent-filter>                  <action android:name="android.intent.action.MAIN" />                    <category android:name="android.intent.category.LAUNCHER" />              </intent-filter>          </activity>      </application>   <!-- 访问网络的权限 -->   <uses-permission android:name="android.permission.INTERNET"/>   <!-- 在SDCard中创建与删除文件权限 -->   <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>   <!-- 往SDCard写入数据权限 -->   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  </manifest>

       2.服务端

    SocketServer.javapackage com.android.socket.server;    import java.io.File;  import java.io.FileInputStream;  import java.io.FileOutputStream;  import java.io.IOException;  import java.io.OutputStream;  import java.io.PushbackInputStream;  import java.io.RandomAccessFile;  import java.net.ServerSocket;  import java.net.Socket;  import java.text.SimpleDateFormat;  import java.util.Date;  import java.util.HashMap;  import java.util.Map;  import java.util.Properties;  import java.util.concurrent.ExecutorService;  import java.util.concurrent.Executors;    import com.android.socket.utils.StreamTool;    public class SocketServer {   private String uploadPath="D:/uploadFile/";   private ExecutorService executorService;// 线程池   private ServerSocket ss = null;   private int port;// 监听端口   private boolean quit;// 是否退出   private Map<Long, FileLog> datas = new HashMap<Long, FileLog>();// 存放断点数据,最好改为数据库存放     public SocketServer(int port) {    this.port = port;    // 初始化线程池    executorService = Executors.newFixedThreadPool(Runtime.getRuntime()      .availableProcessors() * 50);   }     // 启动服务   public void start() throws Exception {    ss = new ServerSocket(port);    while (!quit) {     Socket socket = ss.accept();// 接受客户端的请求     // 为支持多用户并发访问,采用线程池管理每一个用户的连接请求     executorService.execute(new SocketTask(socket));// 启动一个线程来处理请求    }   }     // 退出   public void quit() {    this.quit = true;    try {     ss.close();    } catch (IOException e) {     e.printStackTrace();    }   }     public static void main(String[] args) throws Exception {    SocketServer server = new SocketServer(7878);    server.start();   }     private class SocketTask implements Runnable {    private Socket socket;      public SocketTask(Socket socket) {     this.socket = socket;    }      @Override    public void run() {     try {      System.out.println("accepted connenction from "        + socket.getInetAddress() + " @ " + socket.getPort());      PushbackInputStream inStream = 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(";");       String filelength = items[0].substring(items[0].indexOf("=") + 1);       String filename = items[1].substring(items[1].indexOf("=") + 1);       String sourceid = items[2].substring(items[2].indexOf("=") + 1);       Long id = System.currentTimeMillis();       FileLog log = null;       if (null != sourceid && !"".equals(sourceid)) {        id = Long.valueOf(sourceid);        log = find(id);//查找上传的文件是否存在上传记录       }       File file = null;       int position = 0;       if(log==null){//如果上传的文件不存在上传记录,为文件添加跟踪记录        String path = new SimpleDateFormat("yyyy/MM/dd/HH/mm").format(new Date());        File dir = new File(uploadPath+ 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()){         File logFile = new File(file.getParentFile(), file.getName()+".log");         if(logFile.exists()){          Properties properties = new Properties();          properties.load(new FileInputStream(logFile));          position = Integer.valueOf(properties.getProperty("length"));//读取断点位置         }        }       }              OutputStream outStream = socket.getOutputStream();       String response = "sourceid="+ id+ ";position="+ position+ "\r\n";       //服务器收到客户端的请求信息后,给客户端返回响应信息:sourceid=1274773833264;position=0       //sourceid由服务生成,唯一标识上传的文件,position指示客户端从文件的什么位置开始上传       outStream.write(response.getBytes());              RandomAccessFile fileOutStream = 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;        Properties properties = new Properties();        properties.put("length", String.valueOf(length));        FileOutputStream logFile = 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 FileLog(Long id, String path) {     super();     this.id = id;     this.path = 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;    }     }  }  ServerWindow.javapackage com.android.socket.server;    import java.awt.BorderLayout;  import java.awt.Frame;  import java.awt.Label;  import java.awt.event.WindowEvent;  import java.awt.event.WindowListener;    public class ServerWindow extends Frame{   private SocketServer server;   private Label label;      public ServerWindow(String title){    super(title);    server = new SocketServer(7878);    label = new Label();    add(label, BorderLayout.PAGE_START);    label.setText("服务器已经启动");    this.addWindowListener(new WindowListener() {     @Override     public void windowOpened(WindowEvent e) {      new Thread(new Runnable() {          @Override       public void run() {        try {         server.start();        } catch (Exception e) {         e.printStackTrace();        }       }      }).start();     }          @Override     public void windowIconified(WindowEvent e) {     }          @Override     public void windowDeiconified(WindowEvent e) {     }          @Override     public void windowDeactivated(WindowEvent e) {     }          @Override     public void windowClosing(WindowEvent e) {       server.quit();       System.exit(0);     }          @Override     public void windowClosed(WindowEvent e) {     }          @Override     public void windowActivated(WindowEvent e) {     }    });   }   /**    * @param args    */   public static void main(String[] args) {    ServerWindow window = new ServerWindow("文件上传服务端");     window.setSize(300, 300);     window.setVisible(true);   }    }  StreamTool.javapackage com.android.socket.utils;    import java.io.ByteArrayOutputStream;  import java.io.File;  import java.io.FileOutputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.PushbackInputStream;    public class StreamTool {        public static void save(File file, byte[] data) throws Exception {     FileOutputStream outStream = new FileOutputStream(file);     outStream.write(data);     outStream.close();    }        public static String readLine(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':        break loop;       case '\r':        int c2 = in.read();        if ((c2 != '\n') && (c2 != -1)) in.unread(c2);        break loop;       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;     return String.copyValueOf(buf, 0, offset);   }       /**   * 读取流   * @param inStream   * @return 字节数组   * @throws Exception   */   public static byte[] readStream(InputStream inStream) throws Exception{     ByteArrayOutputStream outSteam = new ByteArrayOutputStream();     byte[] buffer = new byte[1024];     int len = -1;     while( (len=inStream.read(buffer)) != -1){      outSteam.write(buffer, 0, len);     }     outSteam.close();     inStream.close();     return outSteam.toByteArray();   }    }