1. 程式人生 > >javaWeb學習總結——檔案上傳、下載

javaWeb學習總結——檔案上傳、下載

目錄

  • 1、檔案上傳環境搭建
  • 2、檔案上傳程式碼實現
  • 3、關於下載

@
嘿,熊dei,你不得不知道在Web開發中,檔案上傳和下載功能是非常常用的功能,關於檔案上傳,瀏覽器上傳【檔案以流的形式傳輸】——>伺服器端——>Servlet獲取上傳檔案的輸入流——>解析請求引數,這一系列過程下來我這佩奇腦殼都疼,因此我更推薦用apache的開源工具common-fileupload這個檔案上傳元件,common-fileupload上傳元件的jar包可以去apache官網上面下載,也可以在struts的lib資料夾下面找到(不要問我為什麼,因為就算你問我我也不會告訴你struts上傳功能就是基於這個實現,當然你也不一定用過Struts【現在不用去學,用的少了】,再者你也不會這麼閒去lib目錄找),其次common-fileupload依賴於common-io包,所以需要一起下載使用!

1、檔案上傳環境搭建

jar包下載,可以直接搜尋apche官網進行下載,不過現在比較流行mawen管理jar包(不懂mawen?加油吧,要學的東西還很多,mawen是一定要學的而且也很易學,用了mawen你就停不下來,這玩意太便捷了,學會了mawen,你就會明白媽媽為什麼再也不用擔心小明拿U盤去拷小紅的jar包了)



這個時候common-fileupload依賴的common-io包同樣的操作進行下載,之後建立專案,引入jar包

2、檔案上傳程式碼實現

2.1JSP程式碼

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>                                          
        <form action="UploadServet" method="post"  enctype="multipart/form-data">
            學號:<input name="sno" /><br/>
            姓名:<input name="sname" /><br/>
            上傳照片: <input type="file"  name="spicture"/>
            <br/>
            <input type="submit" value="註冊"/>
        </form>
        <a href="DownloadServlet?filename=MIME.png">MIME</a>
        
</body>
</html>

2.2Servlet程式碼

package org.student.servlet;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
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.FileItemFactory;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * Servlet implementation class UploadServet
 */
public class UploadServet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public UploadServet() {
        super();
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=UTF-8");
        // 上傳
        // request.getParameter("sname")
        try {
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
            if (isMultipart) {// 判斷前臺的form是否有 mutipart屬性
//              FileItemFactory factory = new DiskFileItemFactory();
                DiskFileItemFactory factory = new DiskFileItemFactory();
                
                ServletFileUpload upload = new ServletFileUpload(factory);
                
                //設定上傳檔案時 用到的臨時檔案的大小DiskFileItemFactory
                factory.setSizeThreshold(10240);//設定臨時的緩衝檔案大小為10
                factory.setRepository(new File("D:\\study\\uploadtemp"));//設定臨時檔案的目錄
                //控制上傳單個檔案的大小  20KB ServletFileUpload
                upload.setSizeMax(20480);//位元組B
                Thread.sleep(3000);
                
                // 通過parseRequest解析form中的所有請求欄位,並儲存到 items集合中(即前臺傳遞的sno sname
                // spicture此時就儲存在了items中)
                List<FileItem> items = upload.parseRequest(request);
                // 遍歷items中的資料(item=sno sname spicture)
                Iterator<FileItem> iter = items.iterator();
                while (iter.hasNext()) {
                    FileItem item = iter.next();
                    String itemName = item.getFieldName();
                    int sno = -1;
                    String sname = null;
                    // 判斷前臺欄位 是普通form表單欄位(sno sname),還是檔案欄位

                    // request.getParameter() -- iter.getString()
                    if (item.isFormField()) {
                        if (itemName.equals("sno")) {// 根據name屬性 判斷item是sno sname 還是spicture?
                            sno = Integer.parseInt(item.getString("UTF-8"));
                        } else if (itemName.equals("sname")) {
                            sname = item.getString("UTF-8");
                        } else {
                            System.out.println("其他欄位xxx.....");
                        }
                    } else {// spicture 123
                            // 檔案 上傳
                            // 檔名 getFieldName是獲取 普通表單欄位的Name值
                            // getName()是獲取 檔名
                        String fileName = item.getName();//a.txt   a.docx   a.png
                        String ext = fileName.substring(  fileName.indexOf(".")+1 ) ;
                        if(!(ext.equals("png") || ext.equals("gif") ||ext.equals("jpg"))) {
                            System.out.println("圖片型別有誤!格式只能是 png gif  jpg");
                            return ;//終止
                        }
                        // 獲取檔案內容 並上傳
                        // 定義檔案路徑:指定上傳的位置(伺服器路徑)
                        // 獲取伺服器路徑D:\\study\\apache-tomcat-8.5.30\\wtpwebapps\\UpAndDown\\upload
                        // String path =request.getSession().getServletContext().getRealPath("upload") ;
                        String path = "D:\\study\\upload";

                        File file = new File(path, fileName);
                        
                    

                        item.write(file);// 上傳
                        System.out.println(fileName + "上傳成功!");
                        return;
                    }
                }

            }

        }
        catch (FileUploadBase.SizeLimitExceededException e) {//SizeLimitExceededException是FileUploadException的一個子類
            System.out.println("上傳檔案大小超過限制!最大20KB");
        }
        catch (FileUploadException e) 
        {
            e.printStackTrace();
            
        }
        
        // 解析請求
        catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

#### 2.3 檔案上傳注意的問題:
1、為保證伺服器安全,上傳檔案應該放在外界無法直接訪問的目錄下,比如放於WEB-INF目錄下。

  2、為防止檔案覆蓋的現象發生,要為上傳檔案產生一個唯一的檔名。
  
3、如果上傳的目錄在Tomcat目錄中的wtpwebapps下的新建資料夾名為upload ,如下:


則需要注意:
3.1.如果修改程式碼,則在tomcat重新啟動時 會被刪除
原因:當修改程式碼的時候,tomcat會重新編譯一份新的class 並且重新部署(重新建立各種目錄)

3.2.如果不修改程式碼,則不會刪除
原因: 沒有修改程式碼,class仍然是之前的class

因此,為了防止 上傳目錄丟失: a.虛擬路徑

b.直接更換上傳目錄到非tomcat目錄

4、限制上傳:限制類型、限制大小。注意 對檔案的限制條件 寫在parseRequest之前

3、關於下載

下載:不需要依賴任何jar
a.請求(地址a form),請求Servlet
b.Servlet通過檔案的地址 將檔案轉為輸入流 讀到Servlet中
c.通過輸出流 將 剛才已經轉為輸入流的檔案 輸出給使用者
注意:下載檔案 需要設定2個 響應頭:

response.addHeader("content-Type","application/octet-stream" );//MIME型別:二進位制檔案(任意檔案)
response.addHeader("content-Disposition","attachement;filename="+fileName );//fileName包含了檔案字尾:abc.txt

檔案下載程式碼:

package org.student.servlet;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class DownloadServlet
 */
public class DownloadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DownloadServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        //獲取需要下載的檔名
        String fileName = request.getParameter("filename") ;//form  、a  href、 ...Server?a=b
        
        
        //下載檔案:需要設定 訊息頭
        response.addHeader("content-Type","application/octet-stream" );//MIME型別:二進位制檔案(任意檔案)
        response.addHeader("content-Disposition","attachement;filename="+fileName );//fileName包含了檔案字尾:abc.txt
        
        //Servlet通過檔案的地址  將檔案轉為輸入流 讀到Servlet中
        InputStream in = getServletContext().getResourceAsStream("/res/MIME.png") ;
        
        //通過輸出流 將 剛才已經轉為輸入流的檔案  輸出給使用者
        ServletOutputStream out = response.getOutputStream() ;
        byte[] bs = new byte[10];
        int len=-1 ;
        while(  (len=in.read(bs)) != -1) {
            out.write(bs,0,len);
        }
        out.close();
        in.close();
        
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

到這裡,到了最開心的時刻了!!!關於檔案上傳下載的原始碼與筆記已經打包好了QnQ:
連結:https://pan.baidu.com/s/1oyyEkctcvY3AvTsJNkiuuQ 提取碼: