這個功能經常需要用到,索性完整的總結一下:
代碼很簡單,服務端:
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;
}
完整代碼下載: