2010-04-18 8 views
11

Opracowałem aplikację internetową Java EE. Ta aplikacja pozwala użytkownikowi przesłać plik za pomocą przeglądarki. Po przesłaniu pliku przez użytkownika ta aplikacja najpierw zapisuje przesłany plik na serwerze (na którym działa), a następnie przetwarza go.Jak zapisać plik na serwerze (kontener WWW) za pomocą aplikacji WWW Java EE?

Obecnie jestem przechowywania plików na serwerze, co następuje:

try { 
    // formFile represents the uploaded file 
    FormFile formFile = programForm.getTheFile(); 
    String path = getServlet().getServletContext().getRealPath("") + "/" 
     + formFile.getFileName(); 
    System.out.println(path); 
    file = new File(path); 
    outputStream = new FileOutputStream(file); 
    outputStream.write(formFile.getFileData()); 
} 

gdzie, formFile reprezentuje dodany plik.

Teraz problemem jest to, że działa dobrze na niektórych serwerach, ale na niektórych serwerach getServlet().getServletContext().getRealPath("") wraca null więc ostateczna ścieżka że jestem coraz to null/filename a plik nie przechowuje na serwerze.

Po sprawdzeniu API dla ServletContext.getRealPath() metody, znalazłem następujące:

public java.lang.String getRealPath(java.lang.String path)

Zwraca ciąg zawierający rzeczywistą ścieżkę dla danej ścieżki wirtualnej. Na przykład ścieżka "/index.html" zwraca bezwzględną ścieżkę do pliku w systemie plików serwera, która będzie obsługiwana przez żądanie dla "http://host/contextPath/index.html", gdzie ścieżka_kontekstu jest ścieżką kontekstu tego tekstu serwletu.

Rzeczywista ścieżka zwrócona będzie w formie odpowiedniej do komputera i systemu operacyjnego, na którym działa kontener serwletów, w tym odpowiednich separatorów ścieżek. Ta metoda zwraca wartość null, jeśli kontener serwletu nie może przetłumaczyć ścieżki wirtualnej do rzeczywistej ścieżki z jakiegokolwiek powodu (np. Gdy treść jest udostępniana z archiwum .war).

tak, to czy jest jakiś inny sposób, za pomocą których można przechowywać pliki na tych serwerach, które również wraca null dla getServlet().getServletContext().getRealPath("")

Odpowiedz

13

Pisząc do systemu plików z pojemnika Java EE nie jest bardzo zalecane, szczególnie jeśli trzeba przetwarzać pisemnej dane:

  • nie jest transakcyjny
  • szkodzi przenoszenia (co, jeśli są w środowisku klastrowym)
  • to wymaga konfiguracji parametrów zewnętrznych lokalizacji docelowej

Jeśli jest to opcja, by przechowywać pliki w bazie danych lub U se repozytorium JCR (np. Jackrabbit).

+0

@Pascal Chcę przechowywać tylko jeden plik do przetworzenia później. Więc myślę, że nie byłoby dobrym pomysłem przechowywanie tego pliku w bazie danych? Co myślisz? Plik jest plikiem .csv. Jeśli uważasz, że powinienem przechowywać go w bazie danych, to powinienem przechowywać go w formie bajtowej lub w dowolnej innej formie, ponieważ rozmiar pliku może wynosić 100 lub 200 MB. Po drugie, usłyszałem o "Jackrabbit" po raz pierwszy od ciebie i nie wiem, co to jest. Spojrzałem na jego stronę, ale nie znalazłem żadnego samouczka. Czy mógłbyś mi powiedzieć, który z nich byłby lepszy: używając bazy danych lub używając "Jackrabbit"? –

+1

@ Yatendra Istniały wady pisanie do systemu plików "dla rekordu". W przypadku wielu aplikacji może to nie być opcja, ale może nie stanowić problemu. Teraz, aby odpowiedzieć na twoje pytania ... 1) Zapis do bazy danych można wykonać (w LOB); nie jest idealny, ale jeśli nie piszesz tysięcy plików dziennie, powinno być dobrze. 2) Jackrabbit to implementacja JCR API (JSR-170), standardowego API do zapisywania i przechowywania plików w repozytorium treści, a zatem jest alternatywą. Ale korzystanie z repozytorium JCR wydaje się przesadne w przypadku małej aplikacji. * Ja * użyłbym bazy danych. –

+0

Mam podobne pytanie, ale muszę przechowywać małe pliki - więc jest to duże obciążenie, aby użyć jakiejkolwiek bazy danych, która wymaga osobnej instalacji i obsługi. Więc zagłosuj na tę odpowiedź i zagłosuj na odpowiedź @Willa Hartunga - ponieważ dla mnie jest to o wiele prostsze rozwiązanie. – Vladimir

20

SPEC, jedyne „prawdziwe” ścieżka masz gwarancję, aby utworzyć aplet container to katalog tymczasowy.

Można to uzyskać za pośrednictwem ServletContext.gerAttribute ("javax.servlet.context.tempdir"). Pliki te nie są jednak widoczne w kontekście sieci (tzn. Nie można opublikować prostego adresu URL w celu dostarczenia tych plików), a pliki nie są w żaden sposób gwarantowane, aby przetrwać ponowne uruchomienie aplikacji internetowej lub serwera.

Jeśli po prostu potrzebujesz miejsca do przechowywania pliku roboczego przez krótki czas, będzie to działało dobrze.

Jeśli naprawdę potrzebujesz katalogu, możesz ustawić go jako parametr konfiguracyjny (zmienną środowiskową, właściwość Java (np. Java -Dyour.file.here =/tmp/files ...), zestaw parametrów kontekstowych w web.xml, parametr konfiguracyjny przechowywany w bazie danych za pośrednictwem formularza internetowego itp.). Następnie do instalatora należy skonfigurowanie tego katalogu.

Jeśli jednak chcesz później wyświetlić ten plik, będziesz potrzebował mechanizmu specyficznego dla kontenera, aby "zamontować" zewnętrzne katalogi w swojej aplikacji internetowej (Glassfish jako "alternatywne katalogi dokumentów", inne mają podobne koncepcje) lub będziesz musiał napisać serwlet/filtr, aby wyświetlał plik w magazynie poza aplikacją internetową. Ten kod FileServlet jest kompletny i, jak widać, tworzenie własnych, choć nie trudnych, nie jest trywialne, aby zrobić to dobrze.

Edit:

Podstawowa istota jest taka sama, ale zamiast używać "getRealPath", wystarczy użyć "getInitParameter".

Więc:

String filePath = getServletContext().getInitParameter("storedFilePath") + "/" + fileName; 

I na swój sposób.

Edycja ponownie:

chodzi o zawartość ścieżki, dałbym ścieżki bezwzględnej. W przeciwnym razie musisz WIEDZIEĆ, gdzie serwer aplikacji ustawia swoją domyślną ścieżkę podczas egzekwowania, a każdy serwer aplikacji może używać różnych katalogów. Na przykład, uważam, że katalog roboczy dla Glassfish jest katalogiem konfiguracyjnym działającej domeny. Nie jest to szczególnie oczywisty wybór.

Używaj absolutnej ścieżki, zdecydowanie. W ten sposób WIESZ, gdzie znajdują się pliki, i możesz kontrolować uprawnienia dostępu na poziomie systemu operacyjnego dla tego katalogu, jeśli jest to konieczne.

+0

Potrzebuję przechowywać pliki w katalogu, który może przetrwać ponowne uruchomienie serwera i aplikacji. Od ciebie odpowiedź, chciałbym uczynić go parametrem konfiguracyjnym, ustawiając parametr kontekstu. Ale nie rozumiem, jak mogę zapisać plik. Czy możesz podać przykład lub odwołanie do przykładu? –

+0

@Will Pokazałeś mi, jak odzyskać wartość parametru kontekstu, który już znam. Być może mój komentarz nie był jasny. Właściwie, miałem na myśli jaką wartość podałbyś dla parametru kontekstowego "storedFilePath". Względna ścieżka pliku lub bezwzględna ścieżka do pliku? –

+0

Jeśli podasz ścieżkę względną, w jaki sposób przekształcisz ją w ścieżkę absolutną? –

Powiązane problemy