java web(四):request、response一些用法和文件的上傳和下載


  上一篇講了ServletContent、ServletCOnfig、HTTPSession、request、response幾個對象的生命周期、作用范圍和一些用法。今天通過一個小項目運用這些知識。簡單的注冊登錄,文件的上傳和下載。


 大致思路:

  注冊登錄和文件上傳和下載
        注冊成功后跳轉到登錄界面,登陸成功后跳轉到主界面,主界面有上傳和下載功能。
    本次注冊登錄不用數據庫,注冊成功后放到一個map集合中,key值為賬號,value值為密碼。
    注冊成功把當前用戶信息放入map集合並且使用ServletContent對象保存。

 

一:准備階段

  先在WebContent目錄下創建幾個html頁面。

  注冊頁面 register.html :

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>注冊</title>
</head>
<body>
    <br><br><br>
    <!-- action代表form表單提交給那個servlet處理 method指定提交方式:get代表把參數拼接在url后面 post代表把參數放在http請求體中 -->
    <form action="register" method="post">
        <div align="center">
            <span>賬號</span><input type="text" name="username">
            <br>
            <span>密碼</span><input type="password" name="pw">
            <div align="center">
                <input type="submit" value="注冊"/>
            </div>
        </div>
    </form>
</body>
</html>

 

    登錄界面login.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄</title>
</head>
<body>
    <br><br><br>
    <form action="login" method="post">
        <div align="center">
            <span>賬號</span><input type="text" name="username">
            <br>
            <span>密碼</span><input type="password" name="pw">
            <br>
            <div align="center">
                <input type="submit" value="登陸"/>
            </div>
        </div>
    </form>
</body>
</html>

  注冊失敗提示頁面registerError.html:

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>注冊錯誤提示</title>
</head>
<body>
    <div align="center">
        <h1>賬號重復</h1>
        <br>
        <a href="register.html">跳轉到注冊界面</a>
    </div>
</body>
</html>

 

 

  登錄失敗提示頁面loginError.html:

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登錄錯誤提示</title>
</head>
<body>
    <div align="center">
        <h1>賬號密碼錯誤</h1>
        <br>
        <a href="login.html">跳轉到登錄界面</a>
    </div>
    
</body>
</html>

 

 

 

  功能頁面success.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>主界面</title>
</head>
<body>
    <div align="center">
        <!-- enctype這個屬性管理的是表單的MIME編碼。共有三個值可選: 1、application/x-www-form-urlencoded 2、multipart/form-data 3、text/plain 文件上傳值需要指定multipart/form-data -->
        <h1>文件上傳</h1>
        <form action="upload" method="post" enctype="multipart/form-data">
            <input type="text" name="username" />
            <br>
            <input type="file" name="MyImage" />
            <br>
            <input type="submit" value="上傳" />
</form> </div> <br><br> <div align="center"> <!-- 指定幾個文件提供下載
        等后面學了jsp,el表達式和jstl和新標簽庫可以拓展項目
        通過ServletContent對象調用getResourcePaths("/download")可以獲得
        該目錄下的所有內容。【/download/文件名】,然后利用這幾個技術動態的資源列舉出來
        供下載。
--> <h1>文件下載</h1> <a href="download?fileName=1.jpg">1.jpg</a> <br> <a href="download?fileName=movie.wmv">moviemwmv</a> </div> </body> </html>

   文件長傳和下載在webContent目錄下創建兩個文件夾upload和download,在download文件夾下放幾個資源供下載。

  准備階段完成后就可以開始着手寫servlet。

二:編寫注冊和登錄的servlet

  注冊和登錄的servlet代碼【注意:需要把<url-pattern>...</url-pattern>首字母改成小寫和html頁面對應】:

    

package com.briup.servlet.function; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class Register * 注冊 */
public class Register extends HttpServlet { private static final long serialVersionUID = 1L; public Register() { super(); } @Override public void init() throws ServletException { //創建一個Map集合,然后通過ServletContent對象存進去
        Map<String,String> map = new HashMap<String,String>(); this.getServletContext().setAttribute("map", map); } @SuppressWarnings("unchecked") protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲取注冊的賬號和密碼
        String name = request.getParameter("username"); String pw = request.getParameter("pw"); //和map集合對比【不對賬號密碼格式做驗證】
        Map<String,String> map = (Map<String, String>) this.getServletContext().getAttribute("map"); if(map.isEmpty()) { map.put(name, pw); //客戶端重定向到登錄界面
            response.sendRedirect("login.html"); } else { Set<String> key = map.keySet(); //注冊只需要對比賬號,密碼重復無所謂
            for(String s : key) { if(s.equals(name)) { //重定向到注冊錯誤頁面
                    response.sendRedirect("registerError.html"); } else { map.put(name, pw); //客戶端重定向到登錄界面
                    response.sendRedirect("login.html"); } } } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

 

 

 

 

package com.briup.servlet.function; import java.io.IOException; import java.util.Map; import java.util.Set; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class Login * 登錄Servlet */
public class Login extends HttpServlet { private static final long serialVersionUID = 1L; public Login() { super(); } @SuppressWarnings("unchecked") protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //獲取賬號密碼
        String name = request.getParameter("username"); String pw = request.getParameter("pw"); //獲取map集合
        Map<String,String> map = (Map<String, String>) this.getServletContext().getAttribute("map"); if(map.isEmpty()) { //服務器內部跳轉到錯誤界面
            request.getRequestDispatcher("loginError.html").forward(request, response); } else { Set<String> keySet = map.keySet(); for(String s : keySet) { if(s.equals(name) && map.get(s).equals(pw)) { /* * 注意:執行到服務器內部跳轉語句或客服端重定向不會中止函數的執行 * 和return在函數的作用不一樣 * 會繼續執行下去如果跳轉語句和重定向后面還有語句 */
                    //System.out.println(s + "," + map.get(s)); //response.sendRedirect("success.html");
                    request.getRequestDispatcher("success.html").forward(request, response); //需要顯式的加上return
                    return; } } //System.out.println("......"); //如果代碼執行到這里說明賬號或密碼不對 //response.sendRedirect("loginError.html");
            request.getRequestDispatcher("loginError.html").forward(request, response); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub
 doGet(request, response); } }

 

三:文件的下載

  文件的下載和客戶端重定向有點類似,向瀏覽器發送數據,但是要告訴瀏覽器這是文件下載要保存下來而不是當做html頁面解析。

response有個方法:getWriter():PrintWriter;獲得一個字符輸出流,該輸出流可以向客戶端輸出數據。文件下載是否可以通過其寫到頁面?

  傳輸文件一般用字節流,有個類似的方法getOutputStream()可以獲得字節流,通過該字節流向瀏覽器發送數據。

response.setContentType("text/html;charset=utf-8")設置發給瀏覽器的是html頁面【默認】,那么文件下載需要設置為那個?application/x-download。

需要注意的是:我們需要獲取下載文件的絕對路徑,項目會被部署到tomcat安裝目錄下的webapp目錄下,而在src的源代碼則在 "項目名/WEB-INF/classes"下,

使用相對路徑就會出錯。

 

Dowload.java代碼:

 

package com.briup.servlet.function; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URLEncoder; 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 Download * 文件下載 */
public class Download extends HttpServlet { private static final long serialVersionUID = 1L; //把下載目錄配置在web.xml中作為參數
    private String path; @Override public void init() throws ServletException { path = this.getServletConfig().getInitParameter("path"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 獲得用戶需要下載文件的名字
                String fileName = request.getParameter("fileName"); // 下載文件所在目錄的絕對路徑
                String realPath = getServletContext().getRealPath(path); // 設置為下載application/x-download
                response.setContentType("application/x-download"); // 下載文件時顯示的文件保存名稱
                String fileDisplay = "cnblogs_"+fileName; // 中文編碼轉換
                fileDisplay = URLEncoder.encode(fileDisplay, "UTF-8"); //設置響應頭部信息
                response.addHeader("Content-Disposition", "attachment;filename="+fileDisplay); try { ServletOutputStream out = response.getOutputStream(); File file = new File(realPath,fileName); FileInputStream in = new FileInputStream(file); byte[] b = new byte[1024]; int len = -1; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } out.flush(); in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub
 doGet(request, response); } }

 

在web.xml中servlet的配置:

<servlet>
    <description></description>
    <display-name>Download</display-name>
    <servlet-name>Download</servlet-name>
    <servlet-class>com.briup.servlet.function.Download</servlet-class>
    <init-param>
    	<param-name>path</param-name>
    	<param-value>/download</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>Download</servlet-name>
    <url-pattern>/download</url-pattern>
  </servlet-mapping>

   有時候會出現中文亂碼,由於沒有約定好。可以通過requst.setEncoding(編碼)來解析瀏覽器發送過來的數據,通過

response.setEnconding(編碼)告訴瀏覽器以那種編碼解析服務器發送過來的數據。如果有多個servlet需要設置編碼,每個都這樣設置會顯得麻煩,有時候會忘記。

這時候過濾器就可以起到很好的作用。

  

  過濾器,顧名思義,就是過濾掉一些東西。在web中過濾器像一個中介一樣在瀏覽器和服務器中間做一些工作,對web管理的所有web資源:例如Jsp, Servlet, 靜態圖片文件或靜態 html 文件等進行攔截,從而實現一些特殊的功能。比如:不登錄就不允許你訪問主界面,實現URL級別的權限訪問控制、過濾敏感詞匯、壓縮響應信息等一些高級功能。

  實現javax.servlet.Filter接口的類就是過濾器。和Servlet一樣Filter的創建和銷毀也是由WEB服務器負責。不過與Servlet區別的是,它是1>在應用啟動的時候就進行裝載Filter類(與Servlet的load-on-startup配置效果相同)。2>容器創建好Filter對象實例后,調用init()方法。接着被Web容器保存進應用級的集合容器中去了等待着,用戶訪問資源。3>當用戶訪問的資源正好被Filter的url-pattern攔截時,容器會取出Filter類調用doFilter方法,下次或多次訪問被攔截的資源時,Web容器會直接取出指定Filter對象實例調用doFilter方法(Filter對象常駐留Web容器了)。4>當應用服務被停止或重新裝載了,則會執行Filter的destroy方法,Filter對象銷毀。

這次我們使用Filter做個編碼過濾器,代碼:

 

package com.briup.servlet.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** * Servlet Filter implementation class EncodingFilter */
public class EncodingFilter implements Filter { private String encoding; public EncodingFilter() { // TODO Auto-generated constructor stub
 } public void destroy() { // TODO Auto-generated method stub
 } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //設置編碼格式【只對post方式有效】;
 request.setCharacterEncoding(encoding); response.setCharacterEncoding(encoding); //放行;
 chain.doFilter(request, response); } public void init(FilterConfig fConfig) throws ServletException { //我們把編碼設置在web.xml中,如果需要改編碼在配置文件中更改而不需要更改代碼
        encoding = fConfig.getInitParameter("encoding"); } }

 

web.xml配置:

<filter>
    <display-name>EncodingFilter</display-name>
    <filter-name>EncodingFilter</filter-name>
    <filter-class>com.briup.servlet.filter.EncodingFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <!-- "*"通配符代表攔截所有請求 -->
    <url-pattern>/*</url-pattern>
  </filter-mapping>

 運行項目看效果:

 

 

 

四:文件的上傳

  網上有許多的上傳組件,common-fileupload組件是apache的一個開源項目之一,用該組件可實現一次上傳一個或多個文件,並可限制文件大小。

該組件需要用到兩個jar包,我用的是commons-fileupload-1.2.2.jar,commons-io-2.0.1.jar。到網上下載這兩個jar包然后放到WEB-INF/lib目錄下【該目錄可以放本項目用到的jar包,會自動構建,和tomcat服務器下的lib目錄相似,不過后者的作用范圍更大,添加進服務器的項目都可以使用里面的jar包】。

源碼:

  

package com.briup.servlet.function;

import java.io.File;
import java.io.IOException;
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;

/**
 * Servlet implementation class Upload
 */
public class Upload extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	private String path;
	
    public Upload() {
        super();
    }
    
    @Override
    public void init() throws ServletException {
    	path = this.getServletConfig().getInitParameter("path");
    }
    
	@SuppressWarnings("unchecked")
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		
		// 獲得上傳目錄的絕對路徑
		String realpath = this.getServletContext().getRealPath(path);
		System.out.println(path);

		try {
			// 構造一個文件上傳處理對象
			DiskFileItemFactory factory = new DiskFileItemFactory();
			ServletFileUpload upLoad = new ServletFileUpload(factory);

			// 獲得表單中提交內容
			List<FileItem> list = upLoad.parseRequest(request);

			for (FileItem fileItem : list) {
				// fileItem.isFormField()返回true表示是普通的表單組件
				// fileItem.isFormField()返回false表示是上傳

				// 代表普通的輸入框,獲取內容方式不同以往
				if (fileItem.isFormField()) {
					// getName()方法返回的是文件名字 普通表單組件有文件 返回NULL
					String FieldName = fileItem.getFieldName();
					String Content = fileItem.getString("UTF-8");
					// 為了后面可以把普通參數從request中拿出來
					request.setAttribute(FieldName, Content);
				} else {
					// 取得上傳文件的名字
					String fileName = fileItem.getName();
					// 避免文件名字重復
					fileName = System.currentTimeMillis() + fileName;
					File file = new File(realpath, fileName);
					// 把上傳文件進行指定目錄
					fileItem.write(file);
				}
			}
			System.out.println("request.getAttribute(\"username\") = " + request.getAttribute("username"));

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}

 

 web.xml中該servlet的配置:

<servlet>
    <description></description>
    <display-name>Upload</display-name>
    <servlet-name>Upload</servlet-name>
    <servlet-class>com.briup.servlet.function.Upload</servlet-class>
    <init-param>
      <param-name>path</param-name>
      <param-value>/upload</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>Upload</servlet-name>
    <url-pattern>/upload</url-pattern>
  </servlet-mapping>

 

效果瀏覽:

 


免責聲明!

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



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