Servlet pro zpřístupnění fotek, které se nacházejí ve zvláštním adresáři.
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 13 Mar 2010 23:11:01 +0100
changeset 64a2e6f8fc4c34
parent 63 619b0d3732eb
child 65 68f2a5ab49c1
Servlet pro zpřístupnění fotek, které se nacházejí ve zvláštním adresáři.
java/nekurak.net-web/src/java/cz/frantovo/nekurak/servlet/Fotky.java
java/nekurak.net-web/web/WEB-INF/web.xml
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/java/nekurak.net-web/src/java/cz/frantovo/nekurak/servlet/Fotky.java	Sat Mar 13 23:11:01 2010 +0100
     1.3 @@ -0,0 +1,118 @@
     1.4 +package cz.frantovo.nekurak.servlet;
     1.5 +
     1.6 +import java.io.File;
     1.7 +import java.io.FileInputStream;
     1.8 +import java.io.IOException;
     1.9 +import java.io.InputStream;
    1.10 +import java.util.logging.Level;
    1.11 +import java.util.logging.Logger;
    1.12 +import java.util.regex.Pattern;
    1.13 +import javax.servlet.ServletException;
    1.14 +import javax.servlet.ServletOutputStream;
    1.15 +import javax.servlet.http.HttpServlet;
    1.16 +import javax.servlet.http.HttpServletRequest;
    1.17 +import javax.servlet.http.HttpServletResponse;
    1.18 +
    1.19 +/**
    1.20 + * Servlet pro zpřístupnění fotek, které se nacházejí ve zvláštním adresáři.
    1.21 + *
    1.22 + * Má jeden inicializační parametr:
    1.23 + *     adresar – cesta k adresáři na disku, kde se nacházejí fotky.
    1.24 + *     např. /var/www/nekurak.net/fotky
    1.25 + *
    1.26 + * Očekává se struktura adresářů tohoto typu:
    1.27 + *     Plné rozlišení: /var/www/nekurak.net/fotky/original/1.jpg
    1.28 + *     Náhled fotky:   /var/www/nekurak.net/fotky/nahled/1.jpg
    1.29 + * Lze ovlivnit konstantami níže
    1.30 + * @author fiki
    1.31 + */
    1.32 +public class Fotky extends HttpServlet {
    1.33 +
    1.34 +    /** Název inicializačního parametru */
    1.35 +    private static final String INIT_ADRESAR = "adresar";
    1.36 +    /** Název podadresáře obsahujícího fotku v plném rozlišení */
    1.37 +    private static final String PODADRESAR_ORIGINAL = "original";
    1.38 +    /** Název podadresáře obsahujícího výchozí náhled fotky */
    1.39 +    private static final String PODADRESAR_NAHLED = "nahled";
    1.40 +    private static final String PRIPONA = "jpg";
    1.41 +    private static final String LOMITKO = File.separator;
    1.42 +    /** Regulární výraz */
    1.43 +    private static final String VZOR_CESTY = "^" + LOMITKO + "(" + PODADRESAR_ORIGINAL + "|" + PODADRESAR_NAHLED + ")" + LOMITKO + "\\d+\\." + PRIPONA + "$";
    1.44 +    private static final String MIME_TYP = "image/jpeg";
    1.45 +    private File adresar;
    1.46 +    private static final Logger log = Logger.getLogger(Fotky.class.getSimpleName());
    1.47 +
    1.48 +    @Override
    1.49 +    public void init() throws ServletException {
    1.50 +	super.init();
    1.51 +	String initAdresar = getServletConfig().getInitParameter(INIT_ADRESAR);
    1.52 +	adresar = new File(initAdresar);
    1.53 +	if (adresar.isDirectory()) {
    1.54 +	    log.log(Level.INFO, "Servlet „Fotka“ byl úspěšně inicializován.");
    1.55 +	    log.log(Level.INFO, "Adresář s fotkami: " + initAdresar);
    1.56 +	    log.log(Level.INFO, "RegExp cesty: " + VZOR_CESTY);
    1.57 +	} else {
    1.58 +	    throw new ServletException("Servlet „Fotka“ se nepodařilo inicializovat. Cesta: " + initAdresar);
    1.59 +	}
    1.60 +    }
    1.61 +
    1.62 +    /**
    1.63 +     * @param pozadavek pouze GET (není důvod podporovat POST)
    1.64 +     * @param odpoved
    1.65 +     * @throws ServletException např. pokud parametr id není číslo
    1.66 +     * @throws IOException
    1.67 +     */
    1.68 +    @Override
    1.69 +    protected void doGet(HttpServletRequest pozadavek, HttpServletResponse odpoved) throws ServletException, IOException {
    1.70 +
    1.71 +	String cesta = zkontrolujParametr(pozadavek.getPathInfo());
    1.72 +	File soubor = new File(adresar, cesta);
    1.73 +
    1.74 +	if (soubor.isFile() && soubor.canRead()) {
    1.75 +
    1.76 +	    if (soubor.lastModified() > pozadavek.getDateHeader("If-Modified-Since")) {
    1.77 +		/** Soubor se změnil nebo ho klient ještě nemá načtený. */
    1.78 +		odpoved.setContentType(MIME_TYP);
    1.79 +		odpoved.setContentLength((int) soubor.length());
    1.80 +		odpoved.setDateHeader("Last-Modified", soubor.lastModified());
    1.81 +
    1.82 +		ServletOutputStream out = odpoved.getOutputStream();
    1.83 +		InputStream in = new FileInputStream(soubor);
    1.84 +
    1.85 +		try {
    1.86 +		    byte[] bytes = new byte[1024];
    1.87 +		    int bajtuNacteno;
    1.88 +		    while ((bajtuNacteno = in.read(bytes)) != -1) {
    1.89 +			out.write(bytes, 0, bajtuNacteno);
    1.90 +		    }
    1.91 +		} catch (Exception e) {
    1.92 +		    throw new ServletException("Chyba při odesílání obrázku klientovi.", e);
    1.93 +		} finally {
    1.94 +		    in.close();
    1.95 +		    out.close();
    1.96 +		}
    1.97 +	    } else {
    1.98 +		/** Soubor se od posledního načtení klientem nezměnil → není potřeba ho posílat znova. */
    1.99 +		odpoved.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
   1.100 +	    }
   1.101 +
   1.102 +	} else {
   1.103 +	    /** Neexistující nebo nečitelný soubor → HTTP 404 chyba */
   1.104 +	    odpoved.sendError(HttpServletResponse.SC_NOT_FOUND);
   1.105 +	}
   1.106 +    }
   1.107 +
   1.108 +    /**
   1.109 +     * @param cesta cesta požadovaná klientem: request.getPathInfo();
   1.110 +     * @throws ServletException pokud cesta nevyhovuje vzoru
   1.111 +     */
   1.112 +    private static String zkontrolujParametr(String cesta) throws ServletException {
   1.113 +	if (Pattern.matches(VZOR_CESTY, cesta)) {
   1.114 +	    /** cesta je v pořádku → pokračujeme */
   1.115 +	    return cesta;
   1.116 +	} else {
   1.117 +	    /** Chybná cesta → HTTP 500 chyba */
   1.118 +	    throw new ServletException("Chybná cesta k obrázku: " + cesta);
   1.119 +	}
   1.120 +    }
   1.121 +}
     2.1 --- a/java/nekurak.net-web/web/WEB-INF/web.xml	Thu Mar 11 11:55:52 2010 +0100
     2.2 +++ b/java/nekurak.net-web/web/WEB-INF/web.xml	Sat Mar 13 23:11:01 2010 +0100
     2.3 @@ -1,61 +1,80 @@
     2.4  <?xml version="1.0" encoding="UTF-8"?>
     2.5  <web-app version="2.5" 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_2_5.xsd">
     2.6      <session-config>
     2.7 -	<session-timeout>30</session-timeout>
     2.8 +        <session-timeout>30</session-timeout>
     2.9      </session-config>
    2.10 -
    2.11      <welcome-file-list>
    2.12 -	<welcome-file>index.jsp</welcome-file>
    2.13 +        <welcome-file>index.jsp</welcome-file>
    2.14      </welcome-file-list>
    2.15 -
    2.16 +    <!-- <chybovéStránky> -->
    2.17      <error-page>
    2.18 -	<!-- Stránka nenalezena -->
    2.19 -	<error-code>404</error-code>
    2.20 -	<location>/WEB-INF/chyby/404.jsp</location>
    2.21 +        <!-- Stránka nenalezena -->
    2.22 +        <error-code>404</error-code>
    2.23 +        <location>/WEB-INF/chyby/404.jsp</location>
    2.24      </error-page>
    2.25      <error-page>
    2.26 -	<!-- Interní chyba serveru -->
    2.27 -	<error-code>500</error-code>
    2.28 -	<location>/WEB-INF/chyby/500.jsp</location>
    2.29 +        <!-- Interní chyba serveru -->
    2.30 +        <error-code>500</error-code>
    2.31 +        <location>/WEB-INF/chyby/500.jsp</location>
    2.32      </error-page>
    2.33 -
    2.34 +    <!-- </chybovéStránky> -->
    2.35 +    <!-- <definiceServletů> -->
    2.36      <servlet>
    2.37 -	<servlet-name>atom</servlet-name>
    2.38 -	<jsp-file>/WEB-INF/atom/atom.jsp</jsp-file>
    2.39 +        <servlet-name>atom</servlet-name>
    2.40 +        <jsp-file>/WEB-INF/atom/atom.jsp</jsp-file>
    2.41      </servlet>
    2.42 -
    2.43 +    <servlet>
    2.44 +        <description>
    2.45 +	    Servlet zpřístupňující fotky umístěné ve zvláštním adresáři
    2.46 +	    (data oddělená od aplikace).
    2.47 +	</description>
    2.48 +        <servlet-name>fotky</servlet-name>
    2.49 +        <servlet-class>cz.frantovo.nekurak.servlet.Fotky</servlet-class>
    2.50 +        <init-param>
    2.51 +            <description>
    2.52 +		Adresář na disku, který obsahuje fotky podniků.
    2.53 +		Musí existovat při startu aplikace.
    2.54 +	    </description>
    2.55 +            <param-name>adresar</param-name>
    2.56 +            <param-value>/var/www/nekurak.net/fotky</param-value>
    2.57 +        </init-param>
    2.58 +    </servlet>
    2.59 +    <!-- </definiceServletů> -->
    2.60 +    <!-- <mapováníServletů> -->
    2.61      <servlet-mapping>
    2.62 -	<servlet-name>atom</servlet-name>
    2.63 -	<url-pattern>/atom/*</url-pattern>
    2.64 +        <servlet-name>fotky</servlet-name>
    2.65 +        <url-pattern>/fotky/*</url-pattern>
    2.66      </servlet-mapping>
    2.67 -
    2.68 +    <servlet-mapping>
    2.69 +        <servlet-name>atom</servlet-name>
    2.70 +        <url-pattern>/atom/*</url-pattern>
    2.71 +    </servlet-mapping>
    2.72 +    <!-- </mapováníServletů> -->
    2.73      <context-param>
    2.74 -	<!-- Pro případ, že chybí hlavička „Accept-language“ v HTTP požadavku -->
    2.75 -	<param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
    2.76 -	<param-value>cs</param-value>
    2.77 +        <!-- Pro případ, že chybí hlavička „Accept-language“ v HTTP požadavku -->
    2.78 +        <param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
    2.79 +        <param-value>cs</param-value>
    2.80      </context-param>
    2.81 -
    2.82      <!--  <zabezpečení> -->
    2.83      <security-role>
    2.84 -	<role-name>opravneny</role-name>
    2.85 +        <role-name>opravneny</role-name>
    2.86      </security-role>
    2.87      <security-constraint>
    2.88 -	<web-resource-collection>
    2.89 -	    <web-resource-name>Správa Nekuřák.net</web-resource-name>
    2.90 -	    <url-pattern>/sprava/*</url-pattern>
    2.91 -	</web-resource-collection>
    2.92 -	<auth-constraint>
    2.93 -	    <role-name>opravneny</role-name>
    2.94 -	</auth-constraint>
    2.95 +        <web-resource-collection>
    2.96 +            <web-resource-name>Správa Nekuřák.net</web-resource-name>
    2.97 +            <url-pattern>/sprava/*</url-pattern>
    2.98 +        </web-resource-collection>
    2.99 +        <auth-constraint>
   2.100 +            <role-name>opravneny</role-name>
   2.101 +        </auth-constraint>
   2.102      </security-constraint>
   2.103      <login-config>
   2.104 -	<auth-method>FORM</auth-method>
   2.105 -	<realm-name>nekurakNET</realm-name>
   2.106 -	<form-login-config>
   2.107 -	    <form-login-page>/?akce=prihlaseni</form-login-page>
   2.108 -	    <form-error-page>/?akce=prihlaseni&amp;chyba=ano</form-error-page>
   2.109 -	</form-login-config>
   2.110 +        <auth-method>FORM</auth-method>
   2.111 +        <realm-name>nekurakNET</realm-name>
   2.112 +        <form-login-config>
   2.113 +            <form-login-page>/?akce=prihlaseni</form-login-page>
   2.114 +            <form-error-page>/?akce=prihlaseni&amp;chyba=ano</form-error-page>
   2.115 +        </form-login-config>
   2.116      </login-config>
   2.117      <!--  </zabezpečení> -->
   2.118 -
   2.119  </web-app>