SORU
11 Mart 2010, PERŞEMBE


Nasıl dosyaları kullanarak JSP/Sunucu uygulaması sunucuya yüklemek için?

Nasıl kullanarak JSP/Sunucu uygulaması sunucuya dosya yükleyebilir miyim? Bunu denedim:

<form action="upload" method="post">
    <input type="text" name="description" />
    <input type="file" name="file" />
    <input type="submit" />
</form>

Ancak, ben sadece dosya adı, dosya içeriği değil. enctype="multipart/form-data" eklediğimde <form>, request.getParameter() null döndürür.

Araştırma sırasında Apache Common FileUpload sendeledi. Bunu denedim:

FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request); // This line is where it died.

Ne yazık ki, sunucu uygulaması açık bir mesaj ve bir neden olmadan bir istisna attı. Burada 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)

CEVAP
11 Mart 2010, PERŞEMBE


Giriş

Ve bir dosya seçin yükleme şeklinde <input type="file"> HTML bir alan gerekir. HTML specification belirtilen POST yöntemi kullanmak zorunda ve form enctype öznitelik 11* *için ayarlanmış olması gerekir.

<form action="upload" method="post" enctype="multipart/form-data">
    <input type="text" name="description" />
    <input type="file" name="file" />
    <input type="submit" />
</form>

Böyle bir formu gönderdikten sonra, ikili çoklu form verileri enctype set olmadığı zaman daha a different format istek vücutta kullanılabilir.

3.0, Sunucu API Sunucu uygulaması önce doğal destek multipart/form-data yoktu. Sadece varsayılan form application/x-www-form-urlencoded şifre türü destekler. request.getParameter() ve hanımları çok parçalı form verilerini kullanarak null dönecekti. Bu iyi bilinen Apache Commons FileUpload devreye girdi.

Elle ayrıştırma yok!

Teoride ServletRequest#getInputStream() kendine göre ayrıştırabilir. Ancak, bu RFC2388 kesin bilgi gerektiren hassas ve sıkıcı bir iştir. Bunu tek başına yapmak ya da bazı homegrown kütüphane-daha az kod internette başka bir yerde bulunan copypaste etmeye çalışmamalısınız. Birçok online kaynakları bu, roseindia.net gibi zor başarısız oldu. Ayrıca uploading of pdf file bkz. Kullanılan gerçek bir kütüphane (ve dolaylı olarak test!) kullanmalısınız yerine yıllardır milyonlarca kullanıcı tarafından. Böyle bir kütüphane sağlamlığı kanıtlanmıştır.

Zaten Sunucu uygulaması 3.0 veya daha yeni olunca, yerel API kullanın

Kullanıyorsanız en azından Sunucu uygulaması 3.0 (7 Tomcat, JBoss AS 6, Önemli olan 3, vs.), daha sonra sadece standart API sağlanan HttpServletRequest#getPart() bitirirken tek parçalı form veri kalemleri (çoğu Sunucu uygulaması 3.0 uygulamaları aslında Apache Commons FileUpload yorganın altında bu!). Ayrıca, normal form alanları getParameter() her zamanki gibi tarafından kullanılabilir.

İlk ve multipart/form-data isteklerini tanımak ve destek getPart() işe almak böylece izin için @MultipartConfig ile sunucu uygulaması açıklama:

@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
    // ...
}

Daha sonra, aşağıdaki gibi: doPost() uygulamak

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String description = request.getParameter("description"); // Retrieves <input type="text" name="description">
    Part filePart = request.getPart("file"); // Retrieves <input type="file" name="file">
    String fileName = filePart.getSubmittedFileName();
    InputStream fileContent = filePart.getInputStream();
    // ... (do your job here)
}

Sunucu uygulaması 3.1 henüz üzerinde değilken, el ile gönderilen dosya

Part#getSubmittedFileName() Sunucu uygulaması 3.1 tanıtıldı (Tomcat 8, WildFly 4, vb Önemli olan 8,) olduğunu unutmayın. Eğer Sunucu uygulaması 3.1 henüz varsa, o zaman ek yarar bir yöntem gönderilen dosya adı almanız gerekir.

private static String getSubmittedFileName(Part part) {
    for (String cd : part.getHeader("content-disposition").split(";")) {
        if (cd.trim().startsWith("filename")) {
            String fileName = cd.substring(cd.indexOf('=')   1).trim().replace("\"", "");
            return fileName.substring(fileName.lastIndexOf('/')   1).substring(fileName.lastIndexOf('\\')   1); // MSIE fix.
        }
    }
    return null;
}
String fileName = getSubmittedFileName(filePart);

Dosya adı almak için MSIE olarak düzeltmeyi unutmayın. Bu tarayıcı yanlış dosya adı yerine adını birlikte tam dosya yolunu gönderir.

Sunucu uygulaması üzerinde değilken 3.0 henüz, kullan Apache Commons FileUpload

Eğer 3.0 henüz (bu yükseltme zamanı gelmedi mi?) Sunucu uygulaması, oldun. yaygın bir uygulama Apache Commons FileUpload kullanımı multpart ayrıştırmak için bilgi talep formu yapın. User Guide mükemmel ve 68* *(dikkatle iki geçmesi). Ayrıca O ' Reilly var("cos") MultipartRequest, ama (küçük) bazı hatalar var ve aktif olarak yıllardır artık korunmaz. Bunu kullanarak tavsiye etmem. Apache Commons FileUpload hala aktif olarak korunur ve çok olgun şu anda.

Apache Commons FileUpload kullanmak için aşağıdaki dosyaları /WEB-INF/lib en az olması gerekir:

İlk denemeniz commons IO unuttum çünkü büyük olasılıkla başarısız oldu.

Burada UploadServlet Apache Commons FileUpload kullanarak gibi görünebilir nasıl bir açılış için

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
        for (FileItem item : items) {
            if (item.isFormField()) {
                // Process regular form field (input type="text|radio|checkbox|etc", select, etc).
                String fieldName = item.getFieldName();
                String fieldValue = item.getString();
                // ... (do your job here)
            } else {
                // Process form file field (input type="file").
                String fieldName = item.getFieldName();
                String fileName = FilenameUtils.getName(item.getName());
                InputStream fileContent = item.getInputStream();
                // ... (do your job here)
            }
        }
    } catch (FileUploadException e) {
        throw new ServletException("Cannot parse multipart request.", e);
    }

    // ...
}

Aynı isteği üzerine*37, , , *, getReader(), *getInputStream()getParameterValues()*38 vb önceden aramadın çok önemli. Aksi takdirde sunucu uygulaması kap ve vücut okuma isteği ayrıştırmak ve böylece Apache Commons FileUpload boş bir istek vücut olsun. Ayrıca bir bakın.Ç. ServletFileUpload#parseRequest(request) returns an empty list.

FilenameUtils#getName() not. Bu dosya adını almak için MSIE bir düzeltme. Bu tarayıcı yanlış dosya adı yerine adını birlikte tam dosya yolunu gönderir.

Alternatif olarak da şal bu bir Filter ayrıştırır hepsini otomatik olarak yüklenecektir ve malı geri parametermap isteği üzerine böylece devam edersin kullanarak request.getParameter() her zamanki gibi, ve almak yüklenen dosya ile request.getAttribute(). You can find an example in this blog article.

getParameter() null dönen GlassFish3 hata için geçici çözüm

Önemli olan daha eski sürüm 3.1.2 getParameter() null döndürür a bug neyin olduğunu unutmayın. Böyle bir kap yönlendirilmesi ve yükseltme yapamıyorsanız, o zaman bu programı yöntemin yardımıyla getPart() değeri ayıklamak gerekir:

private static String getValue(Part part) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(part.getInputStream(), "UTF-8"));
    StringBuilder value = new StringBuilder();
    char[] buffer = new char[1024];
    for (int length = 0; (length = reader.read(buffer)) > 0;) {
        value.append(buffer, 0, length);
    }
    return value.toString();
}
String description = getValue(request.getPart("description")); // Retrieves <input type="text" name="description">

Tasarruf yüklenen dosya (getRealPath() kullanmayın ya part.write()!)

Disk veya veritabanına düzgün InputStream elde edilen (yukarıda kod parçacıkları gösterildiği gibi fileContent değişken) kaydetme hakkında ayrıntı için aşağıdaki adreslere Başkanı:

Yüklenen dosya hizmet

Doğru istemciye disk veya veritabanı geri kaydedilen dosya hizmet detay için aşağıdaki adreslere Başkanı:

Form Ajaxifying

Ajax (jQuery) kullanarak yüklemek için, aşağıdaki cevaplar için kafa. Form verilerini toplamak için sunucu kodu bunun için değiştirilmesi gerekir! Ancak bu şekilde size cevap olabilir değişti, ama bu oldukça önemsiz (yani yerine yönlendirme için JSP, sadece baskı bazı JSON veya XML, hatta düz metin olarak, ne olursa olsun bir senaryoyu sorumlu Ajax çağrı bekliyor).


Umarım bu yardımcı olur :)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Bryan Adams

    Bryan Adams

    30 Mart 2006
  • Canceriansoul

    Canceriansou

    15 Ocak 2011
  • OVERWERK

    OVERWERK

    6 Temmuz 2010