Javaweb-文件上傳和郵件發送

来源:https://www.cnblogs.com/twq46/archive/2022/08/03/16547570.html
-Advertisement-
Play Games

1.文件上傳 新建空項目 準備工作 在maven倉庫里下載commons io 和 commons fileupload兩個jar包 實用類介紹 文件上傳註意事項 為保證伺服器安全,上傳文件應該放在外界無法直接訪問的目錄下,比如放在WEB-INF目錄下 為防止文件覆蓋現象發生,要為上傳文件產生一個唯 ...


1.文件上傳

新建空項目

準備工作

在maven倉庫里下載commons io 和 commons fileupload兩個jar包

實用類介紹

文件上傳註意事項

  • 為保證伺服器安全,上傳文件應該放在外界無法直接訪問的目錄下,比如放在WEB-INF目錄下

  • 為防止文件覆蓋現象發生,要為上傳文件產生一個唯一的文件名:可以使用時間戳、uuid、MD5等方式解決文件重名問題

  • 要限制上傳文件的最大值

  • 可以上至上傳文件的類型,在收到上傳文件名時,判斷尾碼名是否合法

需要用到的類詳解

ServletFileUpload負責處理上傳的文件數據,並將表單中每個輸入項封裝成一個FileItem對象,在使用ServletFileUpload對象解析請求時需要DiskFileItemFactory對象,所以,我們需要在進行解析工作前構造好DiskFileItemFactory對象,通過ServletFileUpload對象的構造方法或setFileItemFactory()方法設置ServletFileUpload對象的fileItemFactory屬性。

FileItem類

在HTML頁面中必須有name
<form action="" enctype="multipart/form-data" method="post">
    上傳用戶:<input type="text" name="username"><br>
    <p><input type="file" name="file1"></p>
    <p><input type="file" name="file1"></p>
    <p><input type="submit">   <input type="reset"></p>
</form>

瀏覽器表單的類型如果為multipart/form-data,在伺服器端想要獲取數據就要通過流

常用方法介紹

/*isFormField方法用於判斷FIleItem類對象封裝的數據是一個普通文本表單
還是一個文件表單,如果是普通表單欄位則返回true,否則返回false*/
boolean isFormField();

//getName方法用於獲得文件上傳欄位中的文件名
String getName();

//以流的形式返回上傳文件的數據內容
InputStream getInputStream();

//delete方法用來清空FileItem類對象中存放的主體內容
//如果主體內容被保存在臨時文件中,delete方法將刪除該臨時文件
void delete();

ServletFileUpload類

ServletFileUpload負責處理上傳的文件數據,並將表單中每個輸入項封裝成一個FileItem對象中,使用其parseRequest(HttpServletRequest)方法可以將通過表單中每一個Html標簽提交的數據封裝成一個FileItem對象,然後以List列表的形式返回,使用該方法處理上傳文件簡單易用

代碼編寫

FileServlet代碼
package com.tang.servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

public class FileServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //判斷上傳的文件是普通表單還是帶文件的表單
        if(!ServletFileUpload.isMultipartContent(req)){
            return;//終止方法運行,說明這是一個普通表單,直接返回
        }

        //創建上傳文件的保存路徑,建議在WEB-INF路徑下,安全,用戶無法直接訪問上傳的文件
        String uploadPath = this.getServletContext().getRealPath("WEB-INF/upload");
        File uploadFile = new File(uploadPath);
        if(!uploadFile.exists()){//若文件不存在
            uploadFile.mkdir();//創建這個目錄
        }

        //緩存,臨時文件
        //臨時路徑,假如文件超過了預期的大小,我們就把他放到一個臨時文件中,過幾天自動刪除,或則提醒用戶轉存為永久
        String tmpPath = this.getServletContext().getRealPath("WEB-INF/tmp");
        File file = new File(tmpPath);
        if(!file.exists()){//若文件不存在
            file.mkdir();//創建這個臨時目錄
        }

        /*處理上傳的文件,一般都需要通過流來獲取,我們可以使用req.getInputStream(),原生態的文件上
        * 傳流獲取,十分麻煩,但是我們都是建議使用Apache的文件上傳組件來實現,common-fileupload,他需要依賴於commons-io組件*/

        try {
            //1.創建DiskFileItemFactory對象,處理文件上傳路徑或者大小限制的;
            DiskFileItemFactory factory = getDiskFileItemFactory(file);
            //2、獲取ServletFileUpload
            ServletFileUpload upload = getServletFileUpload(factory);
            //3、處理上傳文件。
            String msg = uploadParseRequest(upload,req,uploadPath);
            //Servlet請求轉發消息
            req.setAttribute("msg",msg);
            req.getRequestDispatcher("/info.jsp").forward(req,resp);
        }catch (FileUploadException e) {
            e.printStackTrace();
        }

   }


    public static DiskFileItemFactory getDiskFileItemFactory(File file){
        //1、創建DiskFileItemFactory對象,處理文件上傳路徑或限制文件大小.
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //通過這個工廠設置一個緩衝區,當上傳的文件大小大於緩衝區的時候,將它放到臨時文件中;
        //這裡不設置的話也有預設的。
        factory.setSizeThreshold(1024 * 1024);//緩衝區大小為1M.
        factory.setRepository(file);
        return factory;
    }


    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
        //2、獲取ServletFileUpload。
        ServletFileUpload upload = new ServletFileUpload(factory);
        //監聽文件上傳進度。
        upload.setProgressListener(new ProgressListener() {
            public void update(long pBytesRead, long lpContentLenght, int i) {
                //pBytesRead:已讀取到的文件大小。
                //pContentLenght:文件大小。
                System.out.println("總大小:"+lpContentLenght+"已上傳:"+pBytesRead);//在這裡還可以加進度。
            }
        });
        //處理亂碼問題.
        upload.setHeaderEncoding("UTF-8");
        //設置單個文件的最大值.
        upload.setFileSizeMax(1024 * 1024 * 10);
        //設置總共能夠上傳文件的大小.
        //1024 = 1kb * 1024 = 1M * 10 = 10M
        upload.setSizeMax(1024 * 1024 * 10);
        return upload;
    }


    public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest req,String uploadPath) throws IOException, FileUploadException {
        String msg = "";
        //3、處理上傳文件。
        //把前端的請求解析,封裝成一個FileItem對象,需要從ServletFileUpLoad對象中獲取
        List<FileItem> fileItems = upload.parseRequest(req);
        for (FileItem fileItem : fileItems) {
            if (fileItem.isFormField()) { //判斷是普通表單還是帶文件的表單。
                //getFieldName指的是前端表單控制項的name。
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8");//處理亂碼。
                System.out.println(name + ":" + value);

            }else {//判斷它是帶文件的表單。

                //======================處理文件=======================//

                //拿到文件的名字
                String uploadFileName = fileItem.getName();
                System.out.println("上傳的文件名:" + uploadFileName);
                //可能存在文件不合法的情況
                if (uploadFileName.trim().equals("") || uploadFileName == null) {
                    continue;
                }
                //獲得上傳的文件名,例如/img/girl/ooa.jpg,只需要ooa,其前面的後面的都不需要。
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                //獲得文件的尾碼名。
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);

                    /*
                    如果文件尾碼名fileExtName不是我們所需要的。
                    就直接return,不處理,告訴用戶文件類型不對。
                    */
                    /*可以使用UUID(唯一識別的通用碼),保證文件名唯一。
                    UUID.randomUUID,隨機生一個唯一識別的通用碼。
                    網路傳輸中的東西,都需要序列化。
                    pojo,實體類,如果想要在多個電腦運行,傳輸--->需要把對象都序列化了。
                    JNI=java Native Interface
                    implements Serializable :標記介面,JVM--->java棧 本地方法棧 native-->c++ */
                String uuidPath= UUID.randomUUID().toString();
                System.out.println("文件信息【文件名:"+fileName+"文件類型:"+fileExtName+"】");
                //======================存放地址=======================//
                //存到哪?uploadPath
                //文件真實存在的路徑 realPath
                String realPath = uploadPath+"/"+uuidPath;
                //給每一個文件創建一個對應的文件夾
                File realPathFile = new File(realPath);
                if(!realPathFile.exists()){
                    realPathFile.mkdir();
                }
                //======================文件傳輸=======================//
                //獲得文件上傳的流
                InputStream inputStream = fileItem.getInputStream();

                //創建一個文件輸出流
                FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);

                //創建一個緩衝區
                byte[] buffer = new byte[1024 * 1024];

                //判斷是否讀取完畢
                int len = 0;

                //如果大於0,說明還存在數據
                while ((len=inputStream.read(buffer))>0){
                    fos.write(buffer,0,len);
                }

                //關閉流
                fos.close();
                inputStream.close();

                msg = "文件上傳成功!";
                fileItem.delete();//上傳成功,清除臨時文件
            }
        }
        return msg;
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>FileServlet</servlet-name>
        <servlet-class>com.tang.servlet.FileServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FileServlet</servlet-name>
        <url-pattern>/upload.do</url-pattern>
    </servlet-mapping>
</web-app>

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: twq
  Date: 2022/8/3
  Time: 17:10
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--通過表單上傳文件
    get:上傳文件大小有限制
    post:上傳文件大小沒有限制
--%>
<%--${pageContext.request.contextPath}獲取伺服器路徑--%>
<form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post">
    上傳用戶:<input type="text" name="username"><br>
    <p><input type="file" name="file1"></p>
    <p><input type="file" name="file1"></p>
    <p><input type="submit">   <input type="reset"></p>
</form>
</body>
</html>

info.jsp


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>

運行結果圖

2.郵件發送

電子郵件

  • 要在網路上實現郵件功能,必須要有專門的郵件伺服器。

  • 這些郵件伺服器類似於現實生活中的郵局,它主要負責接收用戶投遞過來的郵件,並把郵件投遞到郵件接收者的電子郵箱中。

  • SMTP伺服器地址:一般是 smtp.xxx.com,比如163郵箱是smtp.163.com,qq郵箱是smtp.qq.com。

  • 電子郵箱(E-Mail地址)的獲得需要在郵件伺服器上進行申請。比如我們要使用QQ郵箱,就需要開通郵箱功能。

傳輸協議

SMTP協議

  • 我們通常把處理用戶smtp請求(郵件發送請求)的伺服器稱之為SMTP伺服器(郵件發送伺服器)。

POP3協議

  • 我們通常把處理用戶pop3請求(郵件接收請求)的伺服器稱之為POP3伺服器(郵件接收伺服器)。

郵件收發送原理圖


原理圖的描述:

  • 大Twq通過smtp協議連接到smtp伺服器,然後發送一封郵件給網易的郵件伺服器.

  • 網易分析發現需要去QQ的郵件伺服器,通過smtp協議將郵件轉投給QQ的smtp伺服器.

  • QQ將接收到的郵件存儲在[email protected]這個郵件賬號的空間中.

  • 小Twq通過Pop3協議連接到Pop3伺服器收取郵件.

  • [email protected]這個郵件賬號的空間中取出郵件.

  • Pop3伺服器將取出來的郵件送到小Twq手中.

註意:有可能你收件人地址,發件人地址等信息都正確了,控制台也列印了正確的信息,但是在收件箱就是收不到信息。這是因為可能收件箱伺服器拒收了你發的郵件(比如認為你的郵件是廣告),這時候可能在垃圾箱里能找到,可能找不到。解決辦法是重覆的郵件內容不要多次發送,或者更換收件箱試試。
8月4號繼續更新


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • vuex狀態管理 概述 vuex主要由state,mutations,actions,getters四部分構成(modules本文暫不闡述) state 全局狀態,只讀 組件讀取state方式 根組件上引入並掛載store對象,其他組件在計算屬性通過$store獲取狀態 可以在計算屬性上使用mapS ...
  • 封裝了一個基於vue的公用SvgIcon組件庫,只需要降svg文件放入指定文件夾,就可以通過文件名綁定到SvgIcon組件上使用該文件。 ...
  • 1. 表格標簽 1.1主要作用 顯示和展示數據美觀、良好。 1.2基本語法 <table> <tr> <td>單元格內的文字</td> ... </tr> ... </table> <table></table>用來定義表格的標簽 <tr></tr>標簽用於定義表格中的行,必須鑲嵌在<table>< ...
  • 在設計網頁的時候常常遇到這種情況:一個元素使用的樣式與另一個元素完全相同,但又添加了額外的樣式。 通常會在 HTML 中給元素定義兩個 class,一個通用樣式,一個特殊樣式。 普通CSS的實現 接下來以警告框為例進行講,解4種類型 | 類型 | 說明 | | | | | info | 信息!請註意 ...
  • 如果你有玩過 🎮 《王者榮耀》、《陰陽師》 等手游,一定註意到過它的啟動動畫、皮膚立繪卡片等場景,經常採用靜態底圖加局部液態流動效果的簡單動畫,本文使用前端開發技術,結合 SVG 和 CSS 來實現類似的液化流動效果。本文包含的知識點主要包括:mask-image 遮罩、feTurbulence ... ...
  • 一個工作薄中快速新建多個數據表 一、建立數據源數表 將所有數據統一錄入到本數據源表中,併進行統一排列數據。 註意:這裡的序號很重要,是對應後面工作表格獲取數據的來源,具體見公式設置。 二、建立一個表格模板 ① 將自己需要的表格進行製作及調整格式。 註意:做好表格列印格式調整。 ② 表格做好讀取表格名 ...
  • 1.用戶定義 在前面的案例中,我們的登錄用戶是基於配置文件來配置的(本質是基於記憶體),但是在實際開發中,這種方式肯定是不可取的,在實際項目中,用戶信息肯定要存入資料庫之中。 Spring Security支持多種用戶定義方式,接下來我們就逐個來看一下這些定義方式。通過前面的介紹(參見3小節),大家對 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...