關於request.getInputStream方法上傳文件


之前有做過一個上傳圖片的功能,找到的資料全部都是用框架做的,當時為了盡快完成任務,就拿過來修修改改直接放線上了。對於我這樣的菜鳥,任務雖然完成了,可當前更重要的是個人的技術提升。然后我又開始亂想了。經理說平時把基礎多看看,嗯,上班也有一年了,年后我也寫了日記進行了深刻的反思,然后重新給自己定位。理所當然的是最開始的一層,就是買家具用的人,對於各種技術都只是研究它是做什么的,怎么使用。只能拿過來用,也只會拿過來用。能力還不足以吃透它的底層和核心。再多的技術拿過來都只是會用。雖然這是做項目必備,而我也可以合格。但從個人角度出發,這樣的事情重復多了,就真的是搬磚了。我想一步一步成為做家具的人,成為植樹人···
想的再多不如踏實的搞點東西,嗯,開搞。任務完結后,我開始嘗試用基礎的servlet,來做這個功能。上傳的原理我個人認為就是將本地文件作為輸入流寫入服務器上的某個目錄下。嗯,按照這個邏輯,我開始找reques提供的方法,HttpServletRequest沒有提供相關的方法,但是ServletRequest提供了一個getInputStream()方法,該方法返回的是檢索ServletInputStream的request的實體的二進制數據。嗯,有點靠譜了。查看servletInputStream的api,解釋是此抽象類提供一個從客戶端讀取二進制數據的輸入流,包含一個高效的readLine的方法,是由container實現的。好了,輸入流找到了,剩下的就是把讀取到的數據寫到某個目錄下對應的文件里。
要一個jsp,提交數據
<body>
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="upload">
<input type="submit" value="submit">
</form>
</body>
剩下的就是在后台把數據給獲取,然后寫入。
public class UploadAction extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
InputStream in=req.getInputStream();

OutputStream out=null;
String path="C:\\Users\\Administrator\\Desktop\\promo\\sub\\test.jpg";
out=new FileOutputStream(path);
int c=0;
while((c=in.read())!=-1){
out.write(c);
out.flush();
}

in.close();
out.close();
}
}
我用圖片測試的,跑完以后,路徑下有了test.jpg,但是打開的話提示文件已經損壞。我了個大艹,又是這個問題!使用firebug看一下,提交的數據的什么的是沒有問題的。這尼瑪問題又是出在哪?按流程走,獲取數據,寫入數據,數據可以寫入,沒問題,那就是獲取的讀取的數據有問題了。將test.jpg改成test.txt跑完以后打開一看,文件竟然有三行明文字符,第一句對應的是Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryOgnVq83gcrdVAbmq,是boundary的值,第二句是Content-Disposition: form-data; name="upload"; filename="1.jpg",包含了jsp中file的參數名,filename的值是上傳文件的名字。第三行Content-Type: image/jpeg,這些都是Header Field中的內容。第四行是空白。也就是說從第四行以后才是文件的內容,也就是ServletInputStream所謂的草泥馬的request的實體的二進制數據!我英文很差啊! Retrieves the body of the request as binary data using a ServletInputStream,這操蛋的the body of the quest到底是啥玩意!好吧,先不管,知道問題在哪里了,那就繞過這個坑,既然獲取的內容不完全是上傳的文件內容,那就需要把不是文件的內容給丟掉。我的思路是,把getInputStream()或取的內容都先生成一個臨時的txt文件,然后再從這個文件里讀取真正的上傳文件的內容。嗯,很可行。接下來就要引入一個新成員,RandomAccessFile.我跟它不熟,也是用到才去了解,嗯,此時此刻,它是我的英雄。隨機文件存取流,能夠在文件的任何位置查找或者寫入數據。這個特性,是無敵的破防,無敵的固定傷害!好,代碼繼續改
public class UploadAction extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
InputStream in=req.getInputStream();

OutputStream out=null;
OutputStream fout=null;
String path="C:\\Users\\Administrator\\Desktop\\promo\\sub\\test.txt";
RandomAccessFile raf=new RandomAccessFile(path,"r");
String filePath="C:\\Users\\Administrator\\Desktop\\promo\\sub\\test.jpg";

out=new FileOutputStream(path);
fout=new FileOutputStream(filePath);
int c=0;
while((c=in.read())!=-1){
out.write(c);
out.flush();
}
this.log(raf.readLine());
this.log(raf.readLine());
this.log(raf.readLine());
this.log(raf.readLine());
int d=0;
while((d=raf.read())!=-1){
fout.write(d);
fout.flush();
}
fout.close();
in.close();
out.close();
}
}
跑完以后圖片果然是正常的出來。然后繼續改進,既然上傳的圖片的名字可以讀取到,那就讓再處理一下,讓名字對應上
public class UploadAction extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
InputStream in=req.getInputStream();

OutputStream out=null;
OutputStream fout=null;
String path="C:\\Users\\Administrator\\Desktop\\promo\\sub\\temp.txt";

String filePath="C:\\Users\\Administrator\\Desktop\\promo\\sub\\";

out=new FileOutputStream(path);
int c=0;
while((c=in.read())!=-1){
out.write(c);
out.flush();
}
String fileName = null;
RandomAccessFile raf=new RandomAccessFile(path,"r");
this.log(raf.readLine());
String []tempName=raf.readLine().split(";");
for(String s:tempName){
if(s.contains("filename")){
String[] ss=s.split("=");
fileName=ss[ss.length-1];
}
}
this.log(raf.readLine());
this.log(raf.readLine());
fout=new FileOutputStream(filePath+fileName.replace("\"", ""));
int d=0;
while((d=raf.read())!=-1){
fout.write(d);
fout.flush();
}
fout.close();
in.close();
out.close();
raf.close();
File file=new File(filePath+"temp.txt".replace("\"", ""));
if(file.exists()){
if(file.delete()){
this.log("finished");
}

}
}
}
到了這里,上傳文件的功能是已經實現了,不過還有一點,就是那個temp.txt文件,最后還要把它給刪掉,這樣就比較圓滿一點,不然總覺的多了點什么
public class UploadAction extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
InputStream in=req.getInputStream();

OutputStream out=null;
OutputStream fout=null;
String path="C:\\Users\\Administrator\\Desktop\\promo\\sub\\temp.txt";

String filePath="C:\\Users\\Administrator\\Desktop\\promo\\sub\\";

out=new FileOutputStream(path);
int c=0;
while((c=in.read())!=-1){
out.write(c);
out.flush();
}
String fileName = null;
RandomAccessFile raf=new RandomAccessFile(path,"r");
this.log(raf.readLine());
String []tempName=raf.readLine().split(";");
for(String s:tempName){
if(s.contains("filename")){
String[] ss=s.split("=");
fileName=ss[ss.length-1];
}
}
this.log(raf.readLine());
this.log(raf.readLine());
fout=new FileOutputStream(filePath+fileName.replace("\"", ""));
int d=0;
while((d=raf.read())!=-1){
fout.write(d);
fout.flush();
}
fout.close();
in.close();
out.close();
raf.close();
File file=new File(filePath+"temp.txt".replace("\"", ""));
if(file.exists()){
if(file.delete()){
this.log("finished");
}

}
}
}
再跑一遍,嗯,沒什么問題了,不過更大的問題又出來了,我上傳圖片什么的小文件是可以的,我手賤的上傳了一部一個多G的電影,然后風扇響了,然后cpu的使用率猛竄到95%,然后我就兩眼一黑,洗洗睡了···


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM