[转载] Android通过Socket发送大文件到服务器
android通过socket发送大文件到服务,并且在服务器接受完后返回一个结果给android。主要的是需要在android通过socket.getOutputStream()传送完文件后,需要关闭socket的OutputStream(socket.shutdownOutput();), 而并不是执行getOutputStream()对象的close()方法,如果执行这个方法,那么socket就关闭了,就接收不到服务器返回的结果 了。如果不关闭客户端的输出流,那么服务器端socket获取输入流对象后,调用这个对象的read方法会在执行完后一直处于等待状态,也就是read阻 塞。socket输入流不同于文件输入流,一般调用in.read(),如果返回-1代表就结束了,但是socket这个输入流的read不会返回-1, (如果客户端在发送完文件后不及时关闭);
android端代码:
- package com.roadview.drivermate.net;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.net.InetSocketAddress;
- import java.net.Socket;
- import android.util.Log;
- import com.roadview.drivermate.common.AppConst;
- public class SocketService {
- String tag = "SocketService";
- File file=null;
- String sendinfo=null;
- //socket执行结果
- public int status;
- public SocketService() {
- super();
- }
- public SocketService(File file, String sendinfo) {
- super();
- this.file = file;
- this.sendinfo = sendinfo;
- }
- /**
- * 上传文件方法(图片,视频,录音)
- * @param file 文件对象
- * @param sendinfo 文件信息
- * @return
- */
- public String sendSocket() {
- String result = null;
- FileInputStream reader = null;
- DataOutputStream out = null;
- DataInputStream in = null;
- Socket socket = new Socket();
- byte[] buf = null;
- try {
- // 连接Socket
- socket.connect(new InetSocketAddress(AppConst.ADDRESS,
- AppConst.PORT), 1000);
- // 1. 读取文件输入流
- reader = new FileInputStream(file);
- // 2. 将文件内容写到Socket的输出流中
- out = new DataOutputStream(socket.getOutputStream());
- out.writeInt(AppConst.UPLOAD);
- out.writeUTF(sendinfo);
- int bufferSize = 20480; // 20K
- buf = new byte[bufferSize];
- int read = 0;
- // 将文件输入流 循环 读入 Socket的输出流中
- while ((read = reader.read(buf, 0, buf.length)) != -1) {
- out.write(buf, 0, read);
- }
- Log.i(tag, "socket执行完成");
- out.flush();
- // 一定要加上这句,否则收不到来自服务器端的消息返回
- socket.shutdownOutput();
- // //获取服务器端的相应
- in = new DataInputStream(socket.getInputStream());
- status = in.readInt();
- result = in.readUTF();
- Log.i(tag, "返回结果:" + status + "," + result);
- } catch (Exception e) {
- Log.i(tag, "socket执行异常:" + e.toString());
- } finally {
- try {
- // 结束对象
- buf = null;
- out.close();
- in.close();
- reader.close();
- socket.close();
- } catch (Exception e) {
- }
- }
- return result;
- }
- }
服务器端代码1:
- package audioTest;
- import java.io.BufferedInputStream;
- import java.io.DataInputStream;
- import java.io.IOException;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.util.Date;
- /**
- *
- * 该类是Socket服务端的入口
- */
- public class Server extends Thread{
- // 端口
- public static int port = 9999;
- private static ServerSocket server = null;
- // 存放录音文件的 文件夹
- private final String AUDIO_RECORD = "D:\\audio_record";
- public void run() {
- if(server == null){
- try{
- //1、新建ServerSocket实例
- server = new ServerSocket(port);
- }catch(IOException e){
- e.printStackTrace();
- }
- }
- System.out.println(new Date().toString() + " \n 服务器启动...");
- while(true){
- try{
- //2、访问ServerSocket实例的accept方法取得一个客户端Socket对象
- Socket client = server.accept();
- if(client == null || client.isClosed()) continue;
- // 判断客户端请求类型
- DataInputStream in = new DataInputStream(new BufferedInputStream(client.getInputStream()));
- switch (in.readInt()) {
- // 上传文件
- case 1:
- new SocketUpLoad(client, AUDIO_RECORD).start();
- break;
- // 下载文件
- case 2:
- new SocketDownLoad(client, AUDIO_RECORD).start();
- break;
- default:
- break;
- }
- }catch(IOException ex){
- ex.printStackTrace();
- }
- }
- }
- public static void main(String[] args) {
- new Server().start();
- }
- }
服务器端代码2:
- package com.roadview.drivermate.socket.service;
- import java.io.BufferedInputStream;
- import java.io.BufferedOutputStream;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.net.Socket;
- import java.util.Date;
- public class SocketUpLoad extends Thread {
- // socket对象
- private Socket client;
- // 保存路径
- private String savepath=AppConst.WEBROOT+AppConst.WEBDIR+"\\";
- //返回路径(相对路径)
- private String filepath="/"+AppConst.WEBDIR+"/";
- public SocketUpLoad(Socket client) {
- this.client = client;
- }
- // 创建目录(不存在则创建)
- public File CreateDir(String dir) {
- File file = new File(dir);
- if (!file.exists()) {
- file.mkdirs();
- }
- return file;
- }
- public void run() {
- if (client == null)
- return;
- DataInputStream in = null;
- BufferedOutputStream fo = null;
- DataOutputStream out = null;
- try {
- // 1、访问Socket对象的getInputStream方法取得客户端发送过来的数据流
- in = new DataInputStream(new BufferedInputStream(
- client.getInputStream()));
- String[] str = in.readUTF().split("\\|");
- //文件名
- String fileName =System.currentTimeMillis()+"."+ str[0].split("\\.")[1]; // 取得附带的文件名
- System.out.println(new Date().toString() + " \n 文件名为:"
- + fileName);
- String filetype=str[1];
- String userid = str[2];// 取用户ID
- //存储路径
- savepath=savepath+filetype+"\\"+userid;
- if (savepath.endsWith("/") == false
- && savepath.endsWith("\\") == false) {
- savepath += "\\";
- }
- System.out.println("保存路径:"+savepath);
- //创建目录
- CreateDir(savepath);
- //返回文件名和路径
- filepath = filepath+filetype+"/"+userid+"/"+fileName;
- System.out.println("返回路径:"+filepath);
- // 2、将数据流写到文件中
- fo = new BufferedOutputStream(new FileOutputStream(new File(
- savepath+"\\"+fileName)));
- int bytesRead = 0;
- byte[] buffer = new byte[1024];
- while ((bytesRead = in.read(buffer, 0, buffer.length)) != -1) {
- fo.write(buffer, 0, bytesRead);
- }
- fo.flush();
- fo.close();
- System.out.println(new Date().toString() + " \n 数据接收完毕");
- // 3、获得Socket的输出流,返回一个值给客户端
- out = new DataOutputStream(new BufferedOutputStream(
- client.getOutputStream()));
- out.writeInt(1);
- out.writeUTF(filepath);
- out.flush();
- } catch (Exception ex) {
- ex.printStackTrace();
- try {
- out.writeInt(0);
- out.flush();
- } catch (IOException e) {
- System.out.println(new Date().toString() + ":" + e.toString());
- }
- } finally {
- try {
- out.close();
- fo.close();
- in.close();
- client.close();
- } catch (IOException e) {
- System.out.println(new Date().toString() + ":" + e.toString());
- }
- }
- }
- }