一:瀏覽器post表單提交
通常的input組件表單提交時,按照form屬性提交的其中enctype=”application/x-www-form-urlencoded”是默認值
<form action="RequestServlet" method="post" enctype="application/x-www-form-urlencoded">
該提交方式只是提交普通表單;對於file組所選中的文件內容是不上傳的,因此需要設置:enctype屬性
enctype="multipart/form-data"
多部分提交方式,但注意編碼問題:對於post方式,瀏覽器會對中文進行編碼處理,發送字節,而普通組件的值得根據pageEncoding=”“的格式編碼。但是對於文件,是會檢測文件本身的編碼格式進行編碼。
因此在後臺我麼獲取的字節集,是根據pageEncoding=”“+文件本身的編碼格式混合的字節集,對於requset.setchar..設置編碼只能解析部分正確的編碼,其餘會亂碼
對於後臺接受的內容除了文件內容,是還有其他部分的識別碼:
InputStream in=request.getInputStream();
int len=-1;
byte[] buf=new byte[1024];
while((len=in.read(buf))!=-1){
System.out.print(new String(buf,"utf-8"));
}
可以看出:
除了組件值:流中具有序列碼,說明嗎等識別碼,並且對於不同編碼的文件以同一編碼流解析,會部分亂碼!
如果要在後臺接受文件,那麼我們必須去解析這些內容,確定有幾個文件,分別是什麼編碼,要拋棄掉識別碼,分別以什麼編碼寫相應文件對應的那段字節。這是十分複雜的。
然而有人幫我做好了解析工具,以便我們直接用就行了,我在這介紹一種:Apache的文件上傳工具
使用該工具解析步驟(只說明基礎版步驟):
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//※下面這句解決上傳文件名的中文亂碼
//注意,下面這句設置中文,如果是“multipart/form-data”表單,可以設置其中file組件的文件名,但對其中的普通表單組件無效。
//注意,下面這句設置中文,如果是我們以前用的“application/x-www-form-urlencoded”表單,可以設置其中的普通表單組件。
request.setCharacterEncoding("utf-8");
//先獲取所接收文件我們要保存到哪裏的路徑
String path = getServletContext().getRealPath("/imgs");
//文件上傳需要臨時目錄(如果不指定,那麼該目錄就是tomcat/temp )
File tempDir = new File("d:/a");
DiskFileItemFactory fileFactory = new DiskFileItemFactory(1024*8, tempDir);//創建用於解析文件的工廠類,同時設置緩衝區的位置和大小
//※※※※思路的入口
ServletFileUpload upload = new ServletFileUpload(fileFactory);
upload.setFileSizeMax(1024*1024*5);//設置每個文件最大爲5M
upload.setSizeMax(1024*1024*8);//所有上傳文件大小之和的最大值,此處設最多能上傳8M
//以下開始解析
try {
List<FileItem> list= upload.parseRequest(request);
for(FileItem fi:list){
if(fi.isFormField()){//普通表單組件,如:<input type="text" name="desc1"/>
String str = fi.getString("utf-8");//※以指定編碼的方式獲取,來解決普通表單組件的中文亂碼問題
System.out.println("普通表單組件..."+str);
}else{//文件組件
String fileName = fi.getName();//文件名
System.out.println("fileName:"+fileName);
//由於上傳的文件“名字”可能會有中文,而服務器目錄當中的資源名稱不能夠用中文,因此要把它轉換成非中文的文件名(要考慮文件名不能重複)
String uuid = UUID.randomUUID().toString().replace("-", "");
String ext = fileName.substring( fileName.lastIndexOf("."));//截取文件的擴展名: .jpg
String newFileName = uuid+ext;
//真正的文件內容在 fi.getInputStream() 當中
FileUtils.copyInputStreamToFile(fi.getInputStream(), new File(path+"/"+newFileName));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
上面代碼我們要注意幾點:
1:request.setCharacterEncoding(“utf-8”);在enctype值不同的情況下能起到什麼作用
2:DiskFileItemFactory 與ServletFileUpload以及FileItem三個類的使用(需要網上下載相應jar包,導入項目中,jdk中無此類)
3:項目文件名不能有中文(原因:瀏覽器資源請求時會對中文編碼;如此,一個名爲:圖片.jpg 到達後臺會編碼成 字節名,服務器根據字節名查文件,又怎麼能查到文件呢?)
4:文件名的唯一性(資源名不能重複,服務器無法區分)
5:中文亂碼問題(代碼有處理)