这篇博客包含2部分:
1.Android Java Socket实现文件上传(一)——客户端
2.Android Java Socket实现文件上传(二)——服务端
接下来为大家带来Android客户端的部分。
实现原理
文件上传,通常都是把文件转换成流传到服务器的,在Java Socket中,提供了一种流——叫做对象流ObjectStream。它能够方便我们以面向对象的方式,直接将一个类对象进行传输。那么针对文件,我们就可以把文件转化成字节数组,然后将这个字节数组封装成一个对象,这样就可以将文件通过ObjectStream流传输到服务器了,服务器接收到这个对象后,将里面的字节数组转化为文件即可。
文件包装类
这里我们自定义一个类,将文件抽象成一个类对象,类对象中,可以增加一些其它的信息,下面我增加了文件的名称和后缀,比如filename.png,这些可能是服务器需要的信息。另外需要说明的是:传输的类对象应该是序列化的对象,下面通过实现Serializable接口来实现。
/**
* 传输文件对象
* @author Administrator
*/
public class FileMsg implements Serializable {
String fileName; // 文件名
String fileType; // 文件类型
byte[] fileData; // 文件数据
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
public byte[] getFileData() {
return fileData;
}
public void setFileData(byte[] fileData) {
this.fileData = fileData;
}
}
文件上传工具类
public class Util {
private static Toast toast;
private static ProgressDialog progressDialog;
private static final String IP = "192.168.0.110"; // 上传文件服务器IP
private static final int PORT = 8100; // 上传文件服务器端口
private static final int timeOut = 30000; // 连接超时时间
/**
* Toast显示
* @param context
* @param content
*/
public static void showToast(Context context, String content) {
if (toast == null) {
toast = Toast.makeText(context, content, Toast.LENGTH_SHORT);
} else {
toast.setText(content);
}
toast.show();
}
/**
* 对话框显示
* @param context
* @param msg
* @param callBack
*/
public static void showConfirmDialog(Context context, String msg, final DialogListener listener) {
AlertDialog.Builder builder = new Builder(context);
builder.setTitle(R.string.dialog_title);
builder.setMessage(msg);
builder.setPositiveButton(R.string.yes, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
listener.onYes();
dialog.dismiss();
}
});
builder.setNegativeButton(R.string.no, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
listener.onNo();
dialog.dismiss();
}
});
builder.setCancelable(false);
builder.create().show();
}
/**
* 进度对话框
* @param context
* @param msg
*/
public static void showProgressDialog(Context context, String msg) {
if (progressDialog == null)
progressDialog = new ProgressDialog(context);
progressDialog.setMessage(msg);
progressDialog.setCancelable(false);
progressDialog.show();
}
/**
* 销毁进度对话框
*/
public static void hideProgressDialog() {
if (progressDialog != null)
progressDialog.hide();
}
/**
* 文件转化为字节数组
* @param f
* @return
*/
public static byte[] getBytesFromFile(File f) {
if (f == null) {
return null;
}
try {
FileInputStream stream = new FileInputStream(f);
ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
for (int n;(n = stream.read(b)) != -1;) {
out.write(b, 0, n);
}
stream.close();
out.close();
return out.toByteArray();
} catch (IOException e) {
}
return null;
}
/**
* socket文件上传
* @param context
* @param file
* @param listener
*/
public static void uploadFileBySocket(final Context context, final File file, final SocketCallBackListener listener) {
new Thread(new Runnable() {
@Override
public void run() {
ObjectInputStream in = null;
ObjectOutputStream out = null;
Socket client = null;
try {
try {
//创建Socket,连接到服务器
client = new Socket();
SocketAddress address = new InetSocketAddress(IP, PORT);
client.connect(address, timeOut); // 设置超时时间
in = new ObjectInputStream(client.getInputStream()); // 从服务器读数据
out = new ObjectOutputStream(client.getOutputStream()); // 向服务器写数据
// 构造传输对象
FileMsg msg = new FileMsg();
msg.setFileName(file.getName().split("\\.")[0]);
msg.setFileType(file.getName().split("\\.")[1]);
msg.setFileData(getBytesFromFile(file));
// 向服务器写数据
out.writeObject(msg);
out.flush();
// 读取服务器返回的信息
String result = (String) in.readObject();
if (result != null && "SUCCESS".equals(result)) {
showToast(context, context.getResources().getString(R.string.upload_success));
listener.onFinish(result);
}
} catch (SocketTimeoutException e) {
showToast(context, context.getResources().getString(R.string.connect_timeout));
listener.onError(e);
} catch (Exception e) {
e.printStackTrace();
showToast(context, context.getResources().getString(R.string.upload_failed));
listener.onError(e);
} finally {
// 释放资源
if (in != null)
in.close();
if (out != null);
out.close();
if (client != null)
client.close();
}
} catch (Exception e) {
e.printStackTrace();
showToast(context, context.getResources().getString(R.string.upload_failed));
listener.onError(e);
}
}
}).start();
}
}
其中工具类中用到的2个接口:
/**
* 对话框回调接口
* @author yangmbin
*/
public interface DialogListener {
public void onYes();
public void onNo();
}
/**
* socket文件上传回调接口
* @author yangmbin
*/
public interface SocketCallBackListener {
public void onFinish(String response);
public void onError(Exception e);
}