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

时间:2022-02-13 14:29:56

通过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();

       }

}