这个功能经常需要用到,索性完整的总结一下:
代码很简单,服务端:
package com.shuyan.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.servlet.ServletException;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class UploadHandleServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String savePath = this.getServletContext().getRealPath(
"/WEB-INF/upload");
File file = new File(savePath);
// 判断上传文件的保存目录是否存在
if (!file.exists() && !file.isDirectory()) {
System.out.println(savePath + "目录不存在,需要创建");
// 创建目录
file.mkdir();
}
// 消息提示
String message = "";
try {
// 使用Apache文件上传组件处理文件上传步骤:
// 1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
// 解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
// 3、判断提交上来的数据是否是上传表单的数据
if (!ServletFileUpload.isMultipartContent(request)) {
// 按照传统方式获取数据
return;
}
// 4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
System.out.println(".............................");
List<FileItem> list = upload.parseRequest(request);
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
for (FileItem item : list) {
// 如果fileitem中封装的是普通输入项的数据
if (item.isFormField()) {
String name = item.getFieldName();
// 解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
// value = new String(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name + "=" + value);
} else {// 如果fileitem中封装的是上传文件
// 得到上传的文件名称,
String filename = item.getName();
System.out.println(filename);
if (filename == null || filename.trim().equals("")) {
continue;
}
// 注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:
// c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
// 处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename = filename
.substring(filename.lastIndexOf("\\") + 1);
// 获取item中的上传文件的输入流
InputStream in = item.getInputStream();
// 创建一个文件输出流
FileOutputStream out = new FileOutputStream(savePath + "\\"
+ filename);
// 创建一个缓冲区
byte buffer[] = new byte[1024];
// 判断输入流中的数据是否已经读完的标识
int len = 0;
// 循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while ((len = in.read(buffer)) > 0) {
// 使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\"
// + filename)当中
out.write(buffer, 0, len);
}
// 关闭输入流
in.close();
// 关闭输出流
out.close();
// 删除处理文件上传时生成的临时文件
item.delete();
message = "文件上传成功!";
}
}
} catch (Exception e) {
message = "文件上传失败!";
e.printStackTrace();
}
request.setAttribute("message", message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
客户端(方式1,socket):
public static boolean post(String path, Map<String, String> params,
FormFile[] files) throws Exception {
final String BOUNDARY = "---------------------------7da2137580612"; // 数据分隔线
final String endline = "--" + BOUNDARY + "--\r\n";// 数据结束标志
int fileDataLength = 0;
for (FormFile uploadFile : files) {// 得到文件类型数据的总长度
StringBuilder fileExplain = new StringBuilder();
fileExplain.append("--");
fileExplain.append(BOUNDARY);
fileExplain.append("\r\n");
fileExplain.append("Content-Disposition: form-data;name=\""
+ uploadFile.getParameterName() + "\";filename=\""
+ uploadFile.getFilname() + "\"\r\n");
fileExplain.append("Content-Type: " + uploadFile.getContentType()
+ "\r\n\r\n");
fileDataLength += fileExplain.length();
if (uploadFile.getInStream() != null) {
fileDataLength += uploadFile.getFile().length();
} else {
fileDataLength += uploadFile.getData().length;
}
fileDataLength += "\r\n".length();
}
StringBuilder textEntity = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {// 构造文本类型参数的实体数据
textEntity.append("--");
textEntity.append(BOUNDARY);
textEntity.append("\r\n");
textEntity.append("Content-Disposition: form-data; name=\""
+ entry.getKey() + "\"\r\n\r\n");
textEntity.append(entry.getValue());
textEntity.append("\r\n");
}
// 计算传输给服务器的实体数据总长度
int dataLength = textEntity.toString().getBytes().length
+ fileDataLength + endline.getBytes().length;
URL url = new URL(path);
int port = url.getPort() == -1 ? 80 : url.getPort();
Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);
OutputStream outStream = socket.getOutputStream();
// 下面完成HTTP请求头的发送
String requestmethod = "POST " + url.getPath() + " HTTP/1.1\r\n";
outStream.write(requestmethod.getBytes());
String accept = "Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n";
outStream.write(accept.getBytes());
String language = "Accept-Language: zh-CN\r\n";
outStream.write(language.getBytes());
String contenttype = "Content-Type: multipart/form-data; boundary="
+ BOUNDARY + "\r\n";
outStream.write(contenttype.getBytes());
String contentlength = "Content-Length: " + dataLength + "\r\n";
outStream.write(contentlength.getBytes());
String alive = "Connection: Keep-Alive\r\n";
outStream.write(alive.getBytes());
String host = "Host: " + url.getHost() + ":" + port + "\r\n";
outStream.write(host.getBytes());
// 写完HTTP请求头后根据HTTP协议再写一个回车换行
outStream.write("\r\n".getBytes());
// 把所有文本类型的实体数据发送出来
outStream.write(textEntity.toString().getBytes());
// 把所有文件类型的实体数据发送出来
for (FormFile uploadFile : files) {
StringBuilder fileEntity = new StringBuilder();
fileEntity.append("--");
fileEntity.append(BOUNDARY);
fileEntity.append("\r\n");
fileEntity.append("Content-Disposition: form-data;name=\""
+ uploadFile.getParameterName() + "\";filename=\""
+ uploadFile.getFilname() + "\"\r\n");
fileEntity.append("Content-Type: " + uploadFile.getContentType()
+ "\r\n\r\n");
outStream.write(fileEntity.toString().getBytes());
if (uploadFile.getInStream() != null) {
// 这里实现了一边读一边写
byte[] buffer = new byte[1024];
int len = 0;
while ((len = uploadFile.getInStream().read(buffer, 0, 1024)) != -1) {
outStream.write(buffer, 0, len);
}
uploadFile.getInStream().close();
} else {
outStream.write(uploadFile.getData(), 0,
uploadFile.getData().length);
}
outStream.write("\r\n".getBytes());
}
// 下面发送数据结束标志,表示数据已经结束
outStream.write(endline.getBytes());
BufferedReader reader = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
if (reader.readLine().indexOf("200") == -1) {// 读取web服务器返回的数据,判断请求码是否为200,如果不是200,代表请求失败
return false;
}
outStream.flush();
outStream.close();
reader.close();
socket.close();
return true;
}
方式2(HTTPclient)
public static boolean postFromHttpClient(String path,
Map<String, String> params, FormFile[] files) {
HttpClient httpclient = null;
HttpResponse response = null;
MultipartEntity entity = new MultipartEntity();
try {
httpclient = new DefaultHttpClient();// 看作是浏览器
HttpPost httppost = new HttpPost(path);
for (FormFile formFile : files) {
FileBody fileBody = new FileBody(formFile.getFile());
entity.addPart("file", fileBody);
}
if (params != null && !params.isEmpty()) {
for (Map.Entry<String, String> entry : params.entrySet()) {
StringBody contentBody = new StringBody(entry.getValue(),
"text/plain", Charset.forName("UTF-8"));
entity.addPart(entry.getKey(), contentBody);
}
}
httppost.setEntity(entity);
response = httpclient.execute(httppost);// 发送post请求
int code = response.getStatusLine().getStatusCode();
System.out.println(response.getStatusLine());
if (code == 200) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
return false;
}
完整代码下载: