Jak mogę wgrać pliki na serwer za pomocą JSP / Servlet? Próbowałem tego:
<form action="upload" method="post">
<input type="text" name="description" />
<input type="file" name="file" />
<input type="submit" />
</form>
Jednak dostaję tylko nazwę pliku, a nie treść pliku. Kiedy dodam enctype="multipart/form-data"
do <form>
, następnie request.getParameter()
wraca null
.
Podczas badań natknąłem się na Apache Common FileUpload . Próbowałem tego:
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request); // This line is where it died.
Niestety serwlet zgłosił wyjątek bez wyraźnego komunikatu i przyczyny. Oto stacktrace:
SEVERE: Servlet.service() for servlet UploadServlet threw exception
javax.servlet.ServletException: Servlet execution threw an exception
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:313)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:637)
java
jsp
jakarta-ee
servlets
file-upload
Thang Pham
źródło
źródło
Odpowiedzi:
Wprowadzenie
Aby przeglądać i wybrać plik do przesłania, potrzebujesz
<input type="file">
pola HTML w formularzu. Jak podano w specyfikacji HTML , musisz użyćPOST
metody, aenctype
atrybut formularza musi być ustawiony na"multipart/form-data"
.Po przesłaniu takiego formularza binarne dane wieloczęściowego formularza są dostępne w treści żądania w innym formacie niż wtedy, gdy
enctype
nie jest ustawiony.Przed serwletem 3.0 interfejs API serwletów nie obsługiwał natywnie
multipart/form-data
. Obsługuje tylko domyślny typ formularzaapplication/x-www-form-urlencoded
. Wszyscyrequest.getParameter()
i małżonkowie wróciliby,null
gdy użyli danych wieloczęściowych. To tutaj pojawił się dobrze znany plik Apache Commons FileUpload .Nie parsuj go ręcznie!
Teoretycznie możesz samodzielnie przeanalizować treść żądania
ServletRequest#getInputStream()
. Jest to jednak dokładna i żmudna praca, która wymaga dokładnej znajomości RFC2388 . Nie powinieneś próbować tego robić samemu lub kopiować własnego kodu bez biblioteki znalezionego gdzie indziej w Internecie. Wiele źródeł internetowych zawiodło w tym mocno, takich jak roseindia.net. Zobacz także przesyłanie pliku pdf . Powinieneś raczej używać prawdziwej biblioteki, która jest używana (i domyślnie testowana!) Przez miliony użytkowników od lat. Taka biblioteka dowiodła swojej solidności.Jeśli korzystasz już z Servlet 3.0 lub nowszego, użyj natywnego API
Jeśli używasz co najmniej Servlet 3.0 (Tomcat 7, Jetty 9, JBoss AS 6, GlassFish 3 itp.), Możesz po prostu użyć standardowego interfejsu API podanego
HttpServletRequest#getPart()
do zbierania poszczególnych elementów danych formularza wieloczęściowego (większość implementacji Servlet 3.0 faktycznie używa Apache Plik Commons Załaduj pod przykryciem!). Ponadto zwykłe pola formularza są dostępnegetParameter()
w zwykły sposób.Najpierw dodaj adnotację do serwletu
@MultipartConfig
, aby umożliwić mu rozpoznawanie i obsługęmultipart/form-data
żądań, a tym samymgetPart()
rozpoczęcie pracy:Następnie zaimplementuj go
doPost()
w następujący sposób:Uwaga
Path#getFileName()
. Jest to poprawka MSIE dotycząca uzyskiwania nazwy pliku. Ta przeglądarka niepoprawnie wysyła pełną ścieżkę pliku wzdłuż nazwy zamiast samej nazwy pliku.Jeśli masz możliwość
<input type="file" name="file" multiple="true" />
przesyłania wielu plików, zbierz je jak poniżej (niestety nie ma takiej metody jakrequest.getParts("file")
):Jeśli nie korzystasz jeszcze z serwletu 3.1, ręcznie pobierz przesłaną nazwę pliku
Uwaga:
Part#getSubmittedFileName()
została wprowadzona w Servlet 3.1 (Tomcat 8, Jetty 9, WildFly 8, GlassFish 4 itp.). Jeśli nie korzystasz jeszcze z serwletu 3.1, potrzebujesz dodatkowej metody narzędzia, aby uzyskać nazwę przesłanego pliku.Zwróć uwagę na poprawkę MSIE dotyczącą uzyskiwania nazwy pliku. Ta przeglądarka niepoprawnie wysyła pełną ścieżkę pliku wzdłuż nazwy zamiast samej nazwy pliku.
Jeśli nie korzystasz jeszcze z Servlet 3.0, użyj Apache Commons FileUpload
Jeśli nie korzystasz jeszcze z Servlet 3.0 (czy nie czas na aktualizację?), Powszechną praktyką jest używanie Apache Commons FileUpload do analizowania żądań danych formularza wieloczęściowego. Ma doskonałą instrukcję obsługi i często zadawane pytania (dokładnie przejrzyj oba). Jest też O'Reilly („ cos ”)
MultipartRequest
, ale ma kilka (drobnych) błędów i nie jest już aktywnie utrzymywany przez lata. Nie polecałbym tego używać. Plik Apache Commons FileUpload jest nadal aktywnie utrzymywany i obecnie bardzo dojrzały.Aby korzystać z Apache Commons FileUpload, musisz mieć co najmniej następujące pliki w swojej aplikacji internetowej
/WEB-INF/lib
:commons-fileupload.jar
commons-io.jar
Twoja pierwsza próba nie powiodła się najprawdopodobniej, ponieważ zapomniałeś o wspólnym We / Wy.
Oto przykładowy przykład tego, jak może wyglądać
doPost()
twójUploadServlet
podczas używania Apache Commons FileUpload:To bardzo ważne, aby nie dzwonić
getParameter()
,getParameterMap()
,getParameterValues()
,getInputStream()
,getReader()
, itp na ten sam wniosek wcześniej. W przeciwnym razie kontener serwletu odczyta i przeanalizuje treść żądania, a zatem Apache Commons FileUpload otrzyma pustą treść żądania. Zobacz także ao ServletFileUpload # parseRequest (request) zwraca pustą listę .Uwaga
FilenameUtils#getName()
. Jest to poprawka MSIE dotycząca uzyskiwania nazwy pliku. Ta przeglądarka niepoprawnie wysyła pełną ścieżkę pliku wzdłuż nazwy zamiast samej nazwy pliku.Alternatywnie możesz również zawinąć to wszystko w
Filter
parsowanie wszystkiego w sposób automatyczny i umieścić rzeczy z powrotem w parametryzacji żądania, abyś mógł nadal używaćrequest.getParameter()
zwykłego sposobu i pobierać przesłany plikrequest.getAttribute()
. Możesz znaleźć przykład w tym artykule na blogu .Obejście problemu z błędem GlassFish3, który
getParameter()
wciąż powracanull
Należy pamiętać, że starsze niż GlassFish wersje 3.1.2 miałem błąd przy czym
getParameter()
powraca jeszczenull
. Jeśli celujesz w taki kontener i nie możesz go zaktualizować, musisz wyodrębnić wartośćgetPart()
za pomocą tej metody narzędzia:Zapisywanie przesłanego pliku (nie używaj
getRealPath()
anipart.write()
!)Przejdź do poniższych odpowiedzi, aby uzyskać szczegółowe informacje na temat prawidłowego zapisywania uzyskanej
InputStream
(fileContent
zmiennej, jak pokazano w powyższych fragmentach kodu) na dysk lub bazę danych:Udostępnianie przesłanego pliku
Przejdź do następujących odpowiedzi, aby uzyskać szczegółowe informacje na temat prawidłowego udostępniania zapisanego pliku z dysku lub bazy danych z powrotem do klienta:
Ajaxifying the form
Przejdź do poniższych odpowiedzi na temat przesyłania za pomocą Ajax (i jQuery). Należy pamiętać, że kod serwletu do gromadzenia danych formularza nie musi być w tym celu zmieniany! Można zmienić tylko sposób, w jaki reagujesz, ale jest to raczej trywialne (tj. Zamiast przekierowywać do JSP, po prostu wydrukuj trochę JSON lub XML, a nawet zwykły tekst, w zależności od tego, czego oczekuje skrypt odpowiedzialny za wywołanie Ajax).
Mam nadzieję, że to wszystko pomoże :)
źródło
request.getParts("file")
i byłem zdezorientowany x_xMultipartConfig
warunek zostanie naruszony (np .maxFileSize
:), wywołanierequest.getParameter()
zwraca null. Czy to celowo? Co się stanie, jeśli otrzymam jakieś zwykłe parametry (tekstowe) przed wywołaniemgetPart
(i sprawdzeniemIllegalStateException
)? Powoduje toNullPointerException
wyrzucenie a, zanim mam szansę sprawdzićIllegalStateException
.String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
częściowo podobny do mnieJeśli zdarzy ci się używać Spring MVC, wykonaj następujące czynności: (Zostawiam to tutaj, na wypadek, gdyby ktoś uznał to za przydatne).
Użyj formularza z
enctype
atrybutem ustawionym na „multipart/form-data
” (Taki sam jak odpowiedź BalusC)W kontrolerze zamapuj parametr żądania,
file
abyMultipartFile
wpisać w następujący sposób:Możesz uzyskać nazwę pliku i rozmiar za pomocą
MultipartFile
'sgetOriginalFilename()
igetSize()
.Przetestowałem to w wersji wiosennej
4.1.1.RELEASE
.źródło
Musisz
common-io.1.4.jar
dołączyć plik do swojegolib
katalogu lub jeśli pracujesz w dowolnym edytorze, takim jak NetBeans, musisz przejść do właściwości projektu i po prostu dodać plik JAR i gotowe.Aby uzyskać
common.io.jar
plik, po prostu google go lub po prostu przejdź do strony internetowej Apache Tomcat, gdzie można bezpłatnie pobrać ten plik. Pamiętaj jednak o jednej rzeczy: pobierz binarny plik ZIP, jeśli jesteś użytkownikiem systemu Windows.źródło
.jar
ale.zip
. Czy masz na myśli.zip
?Bez komponentu lub zewnętrznej biblioteki w Tomcat 6 o 7
Włączanie przesyłania w pliku web.xml :
http://joseluisbz.wordpress.com/2014/01/17/manually-installing-php-tomcat-and-httpd-lounge/#Enabling%20File%20Uploads .
JAK MOŻESZ ZOBACZYĆ :
Przesyłanie plików za pomocą JSP. Akta:
W pliku HTML
W pliku JSP lub serwletu
Edytuj kod, aby spełnić wymagania serwletu, takie jak maksymalny rozmiar pliku , maksymalny rozmiar żądania i inne opcje, które możesz ustawić ...
źródło
Używam wspólnego serwletu dla każdego formularza HTML, niezależnie od tego, czy zawiera on załączniki, czy nie. Ten serwlet zwraca miejsce, w
TreeMap
którym klucze to nazwa jsp Parametry i wartości to Dane wejściowe użytkownika i zapisuje wszystkie załączniki w ustalonym katalogu, a następnie zmieniasz nazwę wybranego katalogu. Oto Połączenia to nasz niestandardowy interfejs posiadający obiekt połączenia. Myślę, że to ci pomożeźródło
W przypadku Spring MVC próbowałem to zrobić od wielu godzin i udało mi się stworzyć prostszą wersję, która działała na zasadzie wprowadzania danych i obrazu.
Kontroler do obsługi
Mam nadzieję, że to pomoże :)
źródło
Inne źródło tego problemu występuje, jeśli używasz Geronimo z osadzonym Tomcat. W takim przypadku po wielu iteracjach testowania commons-io i commons-fileupload problem pojawia się w nadrzędnym module ładującym obsługującym słoiki commons-xxx. Trzeba temu zapobiec. Awaria zawsze występowała o:
Zauważ, że typ listy fileItems zmienił się wraz z bieżącą wersją pliku commons-fileupload, w szczególności
List<FileItem>
w przeciwieństwie do poprzednich wersji, w których był ogólnyList
.Dodałem kod źródłowy commons-fileupload i commons-io do mojego projektu Eclipse, aby prześledzić rzeczywisty błąd i wreszcie uzyskałem wgląd. Po pierwsze, zgłoszony wyjątek jest typu Throwable, a nie podany wyjątek FileIOException, a nawet wyjątek (nie zostaną one uwięzione). Po drugie, komunikat o błędzie jest nieprzejrzysty, ponieważ stwierdził, że nie znaleziono klasy, ponieważ oś 2 nie mogła znaleźć towaru wspólnego. Axis2 nie jest w ogóle używany w moim projekcie, ale istnieje jako folder w podkatalogu repozytorium Geronimo w ramach standardowej instalacji.
Wreszcie znalazłem 1 miejsce, w którym znalazłem działające rozwiązanie, które z powodzeniem rozwiązało mój problem. Musisz ukryć słoiki przed nadrzędnym modułem ładującym w planie wdrażania. Zostało to umieszczone w geronimo-web.xml z moim pełnym plikiem pokazanym poniżej.
źródło
Oto przykład użycia apache commons-fileupload:
źródło
Najprostszym sposobem jest wymyślenie plików i kontrolek wejściowych, bez miliarda bibliotek:
źródło
możesz przesłać plik za pomocą jsp / servlet.
z drugiej strony po stronie serwera. użyj następującego kodu.
źródło
Z tego obiektu musisz pobrać elementy pliku i pola, które następnie możesz zapisać na serwerze w następujący sposób:
źródło
Wysyłając wiele plików do pliku, musimy użyć
enctype="multipart/form-data"
i wysłać wiele plików
multiple="multiple"
w tagu wejściowymźródło
STRONA HTML
PLIK SERWERA
web.xml
Skompiluj powyższy serwlet UploadServlet i utwórz wymagany wpis w pliku web.xml w następujący sposób.
źródło