Android http文件上传-本地+服务器一条龙分析

时间:2022-08-28 11:33:02

本地:

先看下项目结构

Android http文件上传-本地+服务器一条龙分析

MainActivity.java

package com.huxq.uploadexample;

import java.io.File;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity implements OnUploadListener {
// 服务器路径,换成自己的
private String urlString = "http://192.168.1.2:8080/UploadTest/Upload";
/**
* 上传文件的路径
*/
String filePath;
/**
* 上传的文件名
*/
String fileName;
ProgressDialog dialog;
/**
* 在读取文件流的时候,同一进度会多次回调,通过这个标记,只有在进度更新的情况下才会更新ui 节省资源
*/
int oldProcess;

@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
Log.i("process", "process" + msg.arg1);
dialog.setProgress(msg.arg1);
// 第一次没有显示dialog的时候显示dialog
if (!dialog.isShowing()) {
Log.i("process", "show");
dialog.show();
} else {
if (msg.arg1 == 100) {// 提示用户上传完成
dialog.dismiss();
toast("上传完成!");
}
}
};
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initProgressDialog();
}

public void upLoad(View v) {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
// toast("上传");
String sdcardPath = Environment.getExternalStorageDirectory()
.getAbsolutePath();
filePath = sdcardPath + "/Abook/";
File file = new File(filePath);
// 这里我选的是Abook文件夹下第五个文件上传,得根据自己的实际情况来,否则肯定出错。
fileName = file.list()[4];
filePath += fileName;
Log.i("file.size", "size=" + file.list().length + "filePath"
+ filePath);
} else {
toast("没有内存卡");
return;
}
new Thread() {
public void run() {
try {
String response = HttpUtil.sendFile(urlString, filePath,
fileName, MainActivity.this);
Log.i("response", "response" + response);
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}

@Override
public void onUpload(double process) {
process = process * 100;
int currentProcess = (int) process;
dialog.setProgress(currentProcess);
// 避免重复发消息,可以把if给去掉看看会发生什么
if (currentProcess > oldProcess) {
Message msg = handler.obtainMessage();
msg.arg1 = (int) process;
handler.sendMessage(msg);
}
oldProcess = currentProcess;
}

public void initProgressDialog() {
dialog = new ProgressDialog(this);
dialog.setMax(100);
dialog.setProgress(0);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
dialog.setTitle("正在努力上传...");
}

public void toast(String text) {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT)
.show();
}

}
HttpUtil.java

public static String sendFile(String urlPath, String filePath,
String newName,OnUploadListener listener) throws Exception {
String end = "\r\n";
String twoHyphens = "--";
String boundary = "******";

URL url = new URL(urlPath);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
//下载需要将setDoInput方法的参数值设为true
con.setDoInput(true);
//上传需要将setDoOutput方法的参数值设为true
con.setDoOutput(true);
//禁止HttpURLConnection使用缓存
con.setUseCaches(false);
//使用POST请求,必须大写
con.setRequestMethod("POST");
//以下三行设置http请求头信息
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Charset", "UTF-8");
//在模拟web页面向服务器端上传文件时,每个文件的开头需要有一个分界符,
//分界符需要在http请求头中指定。boundary是任意一个字符串,一般为******
con.setRequestProperty("Content-Type", "multipart/form-data;boundary="
+ boundary);

DataOutputStream ds = new DataOutputStream(con.getOutputStream());

ds.writeBytes(twoHyphens + boundary + end);
//上传文件相关信息,这些信息包括请求参数名,上传文件名,文件类型,但并不限于此
ds.writeBytes("Content-Disposition: form-data; "
+ "name=\"file1\";filename=\"" + newName + "\"" + end);
ds.writeBytes(end);

//获得文件的输入流,通过流传输文件。在这里我重写了FileInputStream,为了监听上传进度
CustomFileInputStream fStream = new CustomFileInputStream(filePath);
fStream.setOnUploadListener(listener);
/* 设置每次写入1024bytes */
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];

int length = -1;
// 从文件读取数据至缓冲区
while ((length = fStream.read(buffer)) != -1) {
//将资料写入DataOutputStream中
ds.write(buffer, 0, length);
}
ds.writeBytes(end);
ds.writeBytes(twoHyphens + boundary + twoHyphens + end);

fStream.close();
ds.flush();

//上传完成以后获取服务器的反馈
InputStream is = con.getInputStream();
int ch;
StringBuffer b = new StringBuffer();
while ((ch = is.read()) != -1) {
b.append((char) ch);
}

ds.close();
return b.toString();
}
CustomFileInputStream.java

package com.huxq.uploadexample;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class CustomFileInputStream extends FileInputStream {
private OnUploadListener listener;
private int total, done;
private double process;

public CustomFileInputStream(File file) throws FileNotFoundException {
super(file);
available();
}

public CustomFileInputStream(FileDescriptor fd) {
super(fd);
available();
}

public CustomFileInputStream(String path) throws FileNotFoundException {
super(path);
available();
}

@Override
public int read(byte[] buffer, int byteOffset, int byteCount)
throws IOException {
done += byteCount;
process = 1.0 * done / total;
if (listener != null) {
listener.onUpload(process);
}
return super.read(buffer, byteOffset, byteCount);
}

public void setOnUploadListener(OnUploadListener listener) {
this.listener = listener;
}

@Override
public int available() {
try {
// 获取文件的总大小
total = super.available();
} catch (IOException e) {
e.printStackTrace();
}
return total;
}
}
OnUploadListener.java

package com.huxq.uploadexample;

public interface OnUploadListener {
void onUpload(double process);
}

服务器端:

服务器端通过一个servlet来接收文件流,然后写入磁盘就行了。

Android http文件上传-本地+服务器一条龙分析

Upload.java

package com.huxq.test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
* Servlet implementation class Upload
*/
@WebServlet("/Upload")
public class Upload extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* 文件保存路径
*/
private final String savaPath="E:\\uploads/";

/**
* Default constructor.
*/
public Upload() {
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items;
try {
items = upload.parseRequest(request);
Iterator iter = items.iterator();
// 可以接收多个文件
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
// 普通文本信息处理
String paramName = item.getFieldName();
String paramValue = item.getString();
System.out.println(paramName + ":" + paramValue);
} else {
// 上传文件信息处理
String fileName = item.getName();
byte[] data = item.get();
String filePath = savaPath + fileName;
File file = new File(savaPath);
if (!file.exists()) {
file.mkdirs();
}
System.out.println("filePath:" + filePath);
File file2 = new File(filePath);
if (file2.exists())
file2.delete();
FileOutputStream fos = new FileOutputStream(file2);
fos.write(data);
fos.close();
}
}
response.getWriter().write("UPLOAD_SUCCESS");
} catch (FileUploadException e) {
e.printStackTrace();
response.getWriter().write("UPLOAD_FAILED");
}
}
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

}

这里需要两个jar包,分别是commons-fileupload-1.3.1.jar和commons-io-2.4.jar

所有想说的都在代码里了,如果有不清楚的可以下载下载Demo或者留言一起探讨。