Android通过socket实现上传大文件到服务器

清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>

上传文件,我用了两种方式实现,首先是用对象序列化,即把要上传的数据打包成要上传的对象,然后上传。

需要注意的是:序列化的那两个类一定要相同,包括包名。(其实就是客户端和服务器端的javabean类,不过加上Serializable)

本人由于没有处理好服务器端和客户端的包名而使程序不能执行。

同时: 在客户端进行序列化,在服务器端就进行反序列化。

好了,上代码:

首先是序列化的类:

public class UploadFile  implements Serializable  {
 private String title;
 private byte[] contentdata;
 private String mimetype;
 private  String type;
 private long length;
 public String getTitle() {
  return title;
 }
 public void setTitle(String title) {
  this.title = title;
 }
 public byte[] getContentdata() {
  return contentdata;
 }
 public void setContentdata(byte[] contentdata) {
  this.contentdata = contentdata;
 }
 public String getMimetype() {
  return mimetype;
 }
 public void setMimetype(String mimetype) {
  this.mimetype = mimetype;
 }
 public String getType() {
  return type;
 }
 public void setType(String type) {
  this.type = type;
 }
 public long getLength() {
  return length;
 }
 public void setLength(long length) {
  this.length = length;
 }
  
}

public class MainSocket extends Activity {
private Button butchose=null;
private Button up=null;
private   TextView text=null;
private static String filePath=null;


 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  super.setContentView(R.layout.mainsocket);
  butchose=(Button)super.findViewById(R.id.socketchose);
  text=(TextView)super.findViewById(R.id.socketshow);
  up=(Button)super.findViewById(R.id.socketup);
  butchose.setOnClickListener(new MyButton());
  up.setOnClickListener(new MyButton());
  
 }
 //button按钮的不同实现
 class MyButton implements OnClickListener{

 @Override
 public void onClick(View v) {
  switch (v.getId()) {
 case R.id.socketup://发送文件按钮
 try {
  if(text.getText().toString()==null)
  { Toast.makeText(MainSocket.this, "请选择上传文件", 3).show();}
  sendup();
 } catch (Exception e) {
  e.printStackTrace();
 }
 break;

default:
 break;
}
  
 }


 
 
}
 
 //发送文件函数
 public void sendup() throws Exception{
  final Socket socket=new Socket("服务器ip",8897); //建立socket连接
  BufferedReader buffer=new BufferedReader(new InputStreamReader(socket.getInputStream()));//构建一个缓冲区,用于存放服务器返回的数据
  new Thread(new Runnable(){//开启一个新线程,用于发送数据
  @Override
  public void run() {
   try {
    ObjectOutputStream obj=new ObjectOutputStream(socket.getOutputStream());//对象序列化的应用
    UploadFile file=MainSocket.this.upfile();//从下面那个函数中得到序列化的对象
    obj.writeObject(file);//把对象发送出去
   } catch (IOException e) {
   
    e.printStackTrace();
   }
   
  }}).start();
  String s=buffer.readLine().toString();//得到服务器返回的数据
  System.out.println("-------------------返回的数据是"+s);
  if(s.equals("true")){
   text.setText("操作成功!");
  }
  else{
   text.setText("操作失败");
  }
  socket.close();
 
 }
 //构造序列化对象
 public UploadFile upfile(){
  UploadFile upfile=new UploadFile();
  upfile.setTitle("自行设置");
  upfile.setMimetype("自行设置");
  try {
  File file=new File(filePath);//得到发送的文件
  InputStream in=new FileInputStream(file) ;//打开文件的输出流(前台的输入流)
  ByteArrayOutputStream ous=new ByteArrayOutputStream();//声明一个字节流
  byte[] data=new byte[1024];//缓存数组
  int len=0;
 while((len=in.read(data))!=-1){//把前面输入流的数据送到字节流中
  ous.write(data,0,len);
 }
 upfile.setContentdata(ous.toByteArray());//把字节流的数据送到javabean中,即序列化对象中
 upfile.setLength(file.length());//设置长度
 upfile.setType(filePath.substring(filePath.lastIndexOf(".")+1));
 } catch (Exception e) {
   
  e.printStackTrace();
 }
 return upfile;
 }
 
 
 
}
服务器端:

package lxf.com;

import java.io.IOException;
import java.net.ServerSocket;


public class server {

 public static void main(String[] args) {
 try {
  ServerSocket socket=new ServerSocket(8897);
  while(true){
  new Thread(new ServerThread(socket.accept())).start(); 
  }
 } catch (IOException e) {
  
  e.printStackTrace();
 }

 }

}

服务器端实现类:

package lxf.com;

import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.UUID;

import lxf.socket.UploadFile;

 

 

public class ServerThread implements Runnable {
private String PATH="d:"+File.separator+"lxf"+File.separator;
private UploadFile uploadfile=null;
private Socket socket;
public ServerThread(Socket socekt1){
 this.socket=socekt1;
 System.out.println("建立新的连接");
}
 @Override
 public void run() {
   try {
   
   
   ObjectInputStream input=new ObjectInputStream(socket.getInputStream());//进行反序列化
   uploadfile=new UploadFile();
    this.uploadfile=(UploadFile)input.readObject();//把流数据转换成序列化对象
    System.out.println("文件长短是:"+uploadfile.getLength());
    System.out.println("文件格式:"+uploadfile.getType());
    PrintStream out=new PrintStream(socket.getOutputStream());//建立socket输出流
    save();
    out.println("true");//给客户端应答
  } catch (Exception e) {
   
   e.printStackTrace();
  }
  finally{
 
   
   
  }

 }
 public boolean save() throws  Exception{
  File file=new File(PATH+UUID.randomUUID()+"."+uploadfile.getType());//建立一个文件夹
  if(!file.getParentFile().exists())//父文件不存在建立父文件
  {
   file.getParentFile().mkdir();
  }
  OutputStream output=new FileOutputStream(file);//打开控制台输出流
  output.write(uploadfile.getContentdata());//把数据写入文件
  output.close();
  return true ;
 }

}

由于本人每一步写的很细,标的也很细。大家应该可以看懂。

ObjectInputStream与ObjectOutputStream类所读写的对象必须实现了Seralizable接口。对象中的transient和static类型的成员变量不会被读取和写入。

另外,客户端的布局大家可以自行设置。在这里,还有第二种方法:实现多线程多用户断点续传功能,也是用数据流的方式上传。