Spring MVC的文件上傳和下載以及攔截器

Spring MVC會(huì)根據(jù)請(qǐng)求方法的簽名不同,將請(qǐng)求消息中的信息以一定的方式轉(zhuǎn)換并綁定到請(qǐng)求方法的參數(shù)中胶坠。

1.文件上傳

文件上傳挂谍,必須將表單的method設(shè)置為POST叔壤,并將enctype設(shè)置為multipart/form-data。只有這樣口叙,才能將文件的二進(jìn)制數(shù)據(jù)發(fā)送給服務(wù)器炼绘。

Spring 3.0規(guī)范提供了方法來(lái)處理文件上傳,但是這種上傳需要在Servlet中完成妄田。而Spring MVC封裝了上傳功能俺亮,使用了Apache Commons FileUpload技術(shù)來(lái)實(shí)現(xiàn)了一個(gè)MultipartResolver實(shí)現(xiàn)類。

  • Spring MVC依賴的組件包
compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.3'
  • xml配置
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize">
        <value>10485760</value>
    </property>
    <property name="defaultEncoding">
        <value>UTF-8</value>
    </property>
</bean>
  • 后臺(tái)代碼

新建上傳FileModel

public class FileDataModel implements Serializable {
    private String filename;

    private MultipartFile file;

    public String getFilename() {
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public MultipartFile getFile() {
        return file;
    }

    public void setFile(MultipartFile file) {
        this.file = file;
    }
}

Controller代碼
@Controller
@RequestMapping("file")
public class FileController {

    @RequestMapping("upload")
    public String upload() {
        return "upload";
    }

    @RequestMapping(value = "upload", method = RequestMethod.POST)
    public String uoload(FileDataModel fileDataModel, HttpServletRequest request, Model model) {
        FileResult fileResult = new FileResult();
        try {
            if (fileDataModel.getFilename().isEmpty() || fileDataModel.getFile() == null)
                throw new IllegalArgumentException("上傳文件名稱為空或者無(wú)上傳文件");
            String filePath = request.getServletContext().getRealPath("/files");
            String filename = fileDataModel.getFile().getOriginalFilename();
            File savePath = new File(filePath, filename);
            if (!savePath.getParentFile().exists())
                savePath.getParentFile().mkdir();
            fileDataModel.getFile().transferTo(new java.io.File(filePath + java.io.File.separator + filename));
            fileResult.setTitle("上傳成功");
            fileResult.setMessage("上傳成功");
            fileResult.setSuccess(true);
        } catch (Exception ex) {
            fileResult.setTitle("上傳失斝瓮ァ铅辞!");
            fileResult.setMessage(ex.getMessage());
        }
        model.addAttribute("fileResult", fileResult);
        return "fileresult";
    }
}

前臺(tái)JSP頁(yè)面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Upload</title>
</head>
<body>
<form action="/file/upload" enctype="multipart/form-data" method="post">
    <table>
        <tr>
            <td>文件描述:</td>
            <td><input type="text" name="filename"/></td>
        </tr>
        <tr>
            <td>請(qǐng)選擇文件:</td>
            <td><input type="file" name="file"/></td>
        </tr>
        <tr>
            <td>
                <input type="submit" value="上傳"/>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

1.1Spring MVC的MultipartFile的常用方法

獲取文件數(shù)據(jù)

  • 1.[] getBytes() throws IOException;

獲取文件的MIME類型,如image/jpeg等

  • 2.String getContentType();

獲取文件流

  • 3.InputStream getInputStream() throws IOException;

獲取表單中文件組件的名字

  • 4.String getName();

獲取上傳文件的原名

  • 5.String getOriginalFilename();

獲取文件的字節(jié)大小萨醒,單位為byte

  • 6.long getSize();

是否有上傳的文件

  • 7.boolean isEmpty();

將上傳文件保存到一個(gè)目標(biāo)文件中

  • 8.void transferTo(File dest) throws IOException, IllegalStateException;

2.文件下載

Spring MVC提供了一個(gè)ResponseEntity類型斟珊,使用它可以很方便的定義返回的HttpHeader和HttpStatus

@RequestMapping("download")
public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename, Model model) {
ResponseEntity<byte[]> responseEntity = null;
try {
    String path = request.getServletContext().getRealPath("/files");
    String realPath = path + File.separator + filename;
    File file = new File(realPath);
    HttpHeaders headers = new HttpHeaders();
    String downFileName = new String(filename.getBytes("UTF-8"), "iso-8859-1");
    //通知瀏覽器以attachment(下載方式)打開圖片
    headers.setContentDispositionFormData("attachment", downFileName);
    //以二進(jìn)制流數(shù)據(jù)方式進(jìn)行下載
    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    responseEntity = new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);

} catch (Exception ex) {
    ex.printStackTrace();
}
return responseEntity;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>${requestScope.fileResult.title}</title>
</head>
<body>
   <h1>${requestScope.fileResult.message}</h1><br/>
   <a href="/file/download?filename=${requestScope.fileResult.fileName}">${requestScope.fileResult.fileName}</a>
</body>
</html>

3.攔截器

Interceptor攔截器是Spring MVC中相當(dāng)重要的功能,它的功能作用是攔截用戶的請(qǐng)求并進(jìn)行相對(duì)應(yīng)的處理富纸。比如通過(guò)攔截器進(jìn)行用戶權(quán)限驗(yàn)證囤踩,或者判斷用戶是否已經(jīng)登錄等。

Spring MVC 攔截器是可插拔式的設(shè)計(jì)晓褪。如果需要使用某個(gè)攔截器堵漱,只需要在配置文件中應(yīng)用攔截器即可。

3.1 HandlerInterceptor接口

Spring MVC中的Interceptor攔截器請(qǐng)求是通過(guò)實(shí)現(xiàn)HandlerInterceptor接口來(lái)完成的涣仿。

3.2實(shí)現(xiàn)攔截器

  • 1.自定義類實(shí)現(xiàn)Spring的HandlerInterceptor接口

重要接口

該請(qǐng)求方法將在請(qǐng)求處理之前被調(diào)用勤庐。這個(gè)方法的作用是對(duì)進(jìn)行調(diào)用方法前進(jìn)行一些前置初始化操作,進(jìn)行判斷用戶請(qǐng)求是否可以進(jìn)行下去好港。當(dāng)方法返回false的時(shí)候愉镰,后續(xù)的Interceptor及Controller都不會(huì)繼續(xù)執(zhí)行。

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

該方法是在perHandle返回true時(shí)钧汹,在調(diào)用目標(biāo)方法處理之后丈探,在返回視圖之前調(diào)用。這時(shí)候我們可以針對(duì)Controller處理之后的ModelAndView對(duì)象進(jìn)行操作拔莱。

void postHandle(
        HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
        throws Exception;

該方法是在整個(gè)請(qǐng)求處理結(jié)束之后碗降,也就是在DispatcherServlet渲染了對(duì)應(yīng)的視圖之后執(zhí)行。主要用于清理資源塘秦。

void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;
  • 2.自定義類繼承HandlerInterceptorAdapter

代碼演示

  • 實(shí)現(xiàn)HandlerInterceptor
public class AuthorizationInterceptor implements HandlerInterceptor {

    /**
     * 不攔截用戶登錄頁(yè)面及注冊(cè)頁(yè)面
     */
    private static final String[] IGNORE_URI = {"user/login", "user/signup"};

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        boolean flag = false;
        String servletPath = request.getServletPath();
        for (String url : IGNORE_URI) {
            if (servletPath.contains(url)) {
                flag = true;
                break;
            }
        }
        if (!flag) {
            User user = (User) request.getSession().getAttribute("user");
            if (user == null) {
                request.setAttribute("message", "請(qǐng)先登錄再訪問(wèn)網(wǎng)站");
                request.getRequestDispatcher("user/login").forward(request, response);
            } else
                flag = true;
        }
        return flag;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
  • xml配置
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/home/index"/>
        <bean class="utils.AuthorizationInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

當(dāng)訪問(wèn)home/index的時(shí)候需要進(jìn)行驗(yàn)證

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末讼渊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嗤形,更是在濱河造成了極大的恐慌精偿,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赋兵,死亡現(xiàn)場(chǎng)離奇詭異笔咽,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)霹期,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門叶组,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人历造,你說(shuō)我怎么就攤上這事甩十。” “怎么了吭产?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵侣监,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我臣淤,道長(zhǎng)橄霉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任邑蒋,我火速辦了婚禮姓蜂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘医吊。我一直安慰自己钱慢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布卿堂。 她就那樣靜靜地躺著束莫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪草描。 梳的紋絲不亂的頭發(fā)上览绿,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音陶珠,去河邊找鬼挟裂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛揍诽,可吹牛的內(nèi)容都是我干的诀蓉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼暑脆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼渠啤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起添吗,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沥曹,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妓美,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡僵腺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了壶栋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辰如。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贵试,靈堂內(nèi)的尸體忽然破棺而出琉兜,到底是詐尸還是另有隱情,我是刑警寧澤毙玻,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布豌蟋,位于F島的核電站,受9級(jí)特大地震影響桑滩,放射性物質(zhì)發(fā)生泄漏梧疲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一施符、第九天 我趴在偏房一處隱蔽的房頂上張望往声。 院中可真熱鬧,春花似錦戳吝、人聲如沸浩销。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)慢洋。三九已至,卻和暖如春陆盘,著一層夾襖步出監(jiān)牢的瞬間普筹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工隘马, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留太防,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓酸员,卻偏偏與公主長(zhǎng)得像蜒车,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子幔嗦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容