Widziałem kilka sugestii, takich jak posiadanie katalogu obrazu jako symbolicznego łącza wskazującego na katalog poza kontenerem WWW, ale czy to podejście będzie działać zarówno w środowisku Windows, jak i * nix?
Jeśli przestrzegasz zasad ścieżki systemu plików * nix (tj. Używasz wyłącznie ukośników w przód /path/to/files
), to będzie działać również w systemie Windows bez potrzeby majstrowania przy brzydkich File.separator
konkatenacjach ciągów. Byłoby to jednak skanowane tylko na tym samym dysku roboczym, z którego zostało wywołane to polecenie. Więc jeśli na przykład Tomcat jest zainstalowane na C:
czym /path/to/files
faktycznie wskazywać C:\path\to\files
.
Jeśli wszystkie pliki znajdują się poza aplikacją internetową i chcesz, aby Tomcat DefaultServlet
je obsługiwał, to w zasadzie wszystko, co musisz zrobić w Tomcat, to dodać następujący element Context do znacznika /conf/server.xml
wewnętrznego <Host>
:
<Context docBase="/path/to/files" path="/files" />
W ten sposób będą dostępne przez http://example.com/files/...
. W przypadku serwerów opartych na Tomcat, takich jak JBoss EAP 6.x lub starsze, podejście jest zasadniczo takie samo, zobacz także tutaj . Przykład konfiguracji GlassFish / Payara można znaleźć tutaj, a przykład konfiguracji WildFly można znaleźć tutaj .
Jeśli chcesz mieć kontrolę nad odczytu / zapisu plików siebie, to trzeba stworzyć Servlet
do tego, który w zasadzie tylko pobiera InputStream
z pliku w smaku na przykład FileInputStream
i zapisuje go do OutputStream
z HttpServletResponse
.
W odpowiedzi należy ustawić Content-Type
nagłówek, aby klient wiedział, którą aplikację skojarzyć z podanym plikiem. I powinieneś ustawić Content-Length
nagłówek tak, aby klient mógł obliczyć postęp pobierania, w przeciwnym razie będzie nieznany. I powinieneś ustawić Content-Disposition
nagłówek na, attachment
jeśli chcesz okno dialogowe Zapisz jako , w przeciwnym razie klient spróbuje wyświetlić je w tekście. Na koniec po prostu zapisz zawartość pliku w strumieniu wyjściowym odpowiedzi.
Oto podstawowy przykład takiego serwletu:
@WebServlet("/files/*")
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
Po zmapowaniu na url-pattern
przykład /files/*
, możesz to wywołać http://example.com/files/image.png
. W ten sposób możesz mieć większą kontrolę nad żądaniami niż te DefaultServlet
, na przykład dostarczając domyślny obraz (tj. if (!file.exists()) file = new File("/path/to/files", "404.gif")
Lub coś podobnego ). Korzystając również request.getPathInfo()
jest korzystne przede request.getParameter()
ponieważ jest bardziej przyjazny SEO i inaczej IE nie odbierze poprawną nazwę pliku podczas Save As .
Możesz ponownie użyć tej samej logiki do udostępniania plików z bazy danych. Po prostu wymień new FileInputStream()
na ResultSet#getInputStream()
.
Mam nadzieję że to pomoże.
Zobacz też: