Android通過socket實現上傳大文件到服務器

jopen 9年前發布 | 5K 次閱讀 Java Android

上傳文件,我用了兩種方式實現,首先是用對象序列化,即把要上傳的數據打包成要上傳的對象,然后上傳。

需要注意的是:序列化的那兩個類一定要相同,包括包名。(其實就是客戶端和服務器端的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類型的成員變量不會被讀取和寫入。

另外,客戶端的布局大家可以自行設置。在這里,還有第二種方法:實現多線程多用戶斷點續傳功能,也是用數據流的方式上傳。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!