Загрузка файла на сервер

В спецификацию Java EE 6 включены Servlet 3.0, интерфейс «Part» и аннотация @MultiPartConfig, обеспечивающие простой способ загрузки файлов FileUpload на сервер без каких либо сторонних библиотек. Поэтому любая реализация сервлета 3.0 на серверах типа Tomcat 7.х, JBoss 6.х, GlassFish 3.х дают выгоду при загрузке файла.

С выходом очередной версии JSF 2.2 у разработчиков, использующих данный фреймворк, также появилась возможность легкой загрузки файлов на сервер. В данной статье будет рассмотрен пример FileUpload использования компонента h:inputFile для реализации этой возможности.

Структура примера FileUpload

Структура примера включает компонент DemoBean.java, файлы дескриптора web.xml и конфигурации faces-config.xml, страницы выбора файлов index.xhtml и результатов загрузки success.xhtml. В директории lib размещается библиотечный файл фреймворка JSF 2.2. Файлы загружаются в поддиректорию upload проекта. Структура проекта Eclipse представлена на следующем скриншоте.

Листинг компонента DemoBean.java

import java.io.File;
import java.io.IOException;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.http.Part;

@ManagedBean
@SessionScoped
public class DemoBean 
{
    private Part file1;
    private Part file2;

    private static String DIR = null;
    public Part getFile1()
    {
        return file1;
    }

    public void setFile1(Part file1)
    {
        this.file1 = file1;
    }

    public Part getFile2()
    {
        return file2;
    }

    public void setFile2(Part file2) {
        this.file2 = file2;
    }

    private static void setDirUpload()
    {
        ServletContext servletContext = (ServletContext)FacesContext
                                               .getCurrentInstance()
                                               .getExternalContext()
                                               .getContext();
        String path = servletContext.getRealPath("/");
        File fl = new File(path + "/upload");
        DIR = fl.getPath() + File.separator;
        // System.out.println (DIR);
    }
    public String upload() throws IOException
    {
        if (DIR == null)
            setDirUpload();
        file1.write(DIR + getFilename(file1));
        file2.write(DIR + getFilename(file2));
        return "success?faces-redirect=true";
    }

    private static String getFilename(Part part) 
    {
        for (String file : part.getHeader("content-disposition")
                               .split(";")) {
            if (file.trim().startsWith("filename")) {
                String filename = file.substring(file.indexOf('=') + 1)
                                      .trim().replace("\"", "");
                return filename.substring(filename.lastIndexOf('/') + 1)
                                              .substring(filename
                                              .lastIndexOf('\\') + 1);
            }
        }
        return null;
    }
}

В компоненте DemoBean.java определены поля файлов (file1, file2) типа Part с методами get/set и метод upload(), который возвращает наименование страницы success без расширения (т.е. без «.xhtml») согласно упрощенной навигации фреймворка JSF. Для «полного» перехода на страницу success.xhtml используется параметр «?faces-redirect=true».

Вспомогательный метод setDirUpload() позволяет определить путь к директории upload приложения через класс ServletContext. Следует обратить внимание, что при работе приложения под управлением IDE (Eclipse) будет определена несколько иная директория, поскольку среда разработки формирует свою рабочую директорию в workspace проектов. Если расскоментировать строку вывода в консоль полного пути директории DIR, то можно будет увидеть что-то подобное
D:\projects\eclipse\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\UploadFile\

Листинг конфигурации приложения faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    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-facesconfig_2_2.xsd"
    version="2.2">

</faces-config>

Файл конфигурации faces-config.xml примера FileUpload не используется, поскольку последние версии допускают облегченную навигацию. В этой связи метод upload() компонента DemoBean возвращает адрес страницы success без расширения.

Листинг дескриптора приложения web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                       http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>
</web-app>

В дескрипторе приложения определяются стандартные параметры - уровень контекста Development, сервлет FacesServlet, timeout 30 и открываемая страница по умолчанию faces/index.xhtml.

Листинг страницы index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
               "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>File Upload</title>
    </h:head>
    <h:body>
        <h3>Загрузка файлов на сервер</h3>
        <h:form enctype="multipart/form-data">
            <p><h:inputFile value="" style="width:400px;" /></p>
            
            <p><h:inputFile value="" style="width:400px;" /></p>
            <h:commandButton value="Загрузить" action=""/>
        </h:form>
    </h:body>
</html>

На странице загрузки файлов на сервер необходимо выбрать файлы и нажать кнопку «Загрузить». Компонент фреймворка JSF h:inputFile работает с файловой системой на компьютера пользователя и позволяет не напрягаясь с помощью мышки выбрать необходимый файл. В атрибуте value необходимо указать соответствующие «объекты» типа Part компонента JavaBean.

Интерфейс страницы index.xhtml представлен на следующем скриншоте.

При нажатии на кнопку «Загрузить» будет вызван метод upload() компонента DemoBean и сервер откроет страницу success.xhtml.

Листинг страницы success.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
               "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>File Upload</title>
    </h:head>
    <h:body>
        <h2>Загрузка файлов</h2>
        <i>Файлы загружены на сервер!</i>
    </h:body>
</html>

На странице успешной загрузки файлов приводится соответствующее сообщение. Интерфейс страницы success.xhtml представлен на следующем скриншоте.

Обратите внимание на адрес страницы (URL) - «success.xhtml». Если бы метод upload() класса DemoBean.java вернул только «success», а не «success?faces-redirect=true», то в адресе строки осталась бы страница index.xhtml.

Скачать пример FileUpload

Исходный код рассмотренного примера FileUpload в виде проекта Eclipse можно скачать здесь (2.71 Мб). Проект включает javax.faces-2.2.0.jar.

  Рейтинг@Mail.ru