2015-03-31 8 views
10

Sto utilizzando spark per sviluppare un'applicazione Web; il problema si verifica quando voglio caricare un file:spark java: come gestire l'immissione multipart/form-data?

public final class SparkTesting 
{ 
    public static void main(final String... args) 
    { 
     Spark.staticFileLocation("/site"); 

     Spark.port(8080); 

     Spark.post("/upload", (request, response) -> { 
      final Part uploadedFile = request.raw().getPart("uploadedFile"); 
      final Path path = Paths.get("/tmp/meh"); 
      try (final InputStream in = uploadedFile.getInputStream()) { 
       Files.copy(in, path); 
      } 

      response.redirect("/"); 
      return "OK"; 
     }); 
    } 
} 

ma ottengo questo errore:

[qtp509057984-36] ERROR spark.webserver.MatcherFilter - 
java.lang.IllegalStateException: No multipart config for servlet 
    at org.eclipse.jetty.server.Request.getPart(Request.java:2039) 
    at javax.servlet.http.HttpServletRequestWrapper.getPart(HttpServletRequestWrapper.java:361) 
    at com.github.fge.grappa.debugger.web.SparkTesting.lambda$main$0(SparkTesting.java:20) 
    at com.github.fge.grappa.debugger.web.SparkTesting$$Lambda$1/920011586.handle(Unknown Source) 
    at spark.SparkBase$1.handle(SparkBase.java:264) 
    at spark.webserver.MatcherFilter.doFilter(MatcherFilter.java:154) 
    at spark.webserver.JettyHandler.doHandle(JettyHandler.java:60) 
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:179) 
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136) 
    at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:52) 
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) 
    at org.eclipse.jetty.server.Server.handle(Server.java:451) 
    at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:252) 
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:266) 
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:240) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:596) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:527) 
    at java.lang.Thread.run(Thread.java:745) 

E anche se cerco e specificare il tipo in modo esplicito, come in:

Spark.post("/upload", "multipart/form-data", etc etc) 

non funzionerà ancora.

Probabilmente potrei trovare una libreria per analizzare i dati multipart/form, afferrare l'intero contenuto e solo analizzare me stesso, ma sarebbe uno spreco.

Posso configurare la scintilla per gestire tale caso?

risposta

4

Con l'aggiunta di un paio di righe di codice per aggiungere la configurazione più parti, è possibile gestire/form-data multipart senza una libreria esterna:

public Object handle(Request request, Response response) { 
    MultipartConfigElement multipartConfigElement = new MultipartConfigElement("/tmp"); 
    request.raw().setAttribute("org.eclipse.multipartConfig", multipartConfigElement); 
    .... 
    Part file = request.raw().getPart("file"); //file is name of the upload form 
} 

Fonte: http://deniz.dizman.org/file-uploads-using-spark-java-micro-framework/

+0

come caricare file di tali immagini in src/main/resources, che posso accedervi? –

4

ho usato Apache Commons-fileupload per gestire questo.

post("/upload", (req, res) -> { 
final File upload = new File("upload"); 
if (!upload.exists() && !upload.mkdirs()) { 
    throw new RuntimeException("Failed to create directory " + upload.getAbsolutePath()); 
} 

// apache commons-fileupload to handle file upload 
DiskFileItemFactory factory = new DiskFileItemFactory(); 
factory.setRepository(upload); 
ServletFileUpload fileUpload = new ServletFileUpload(factory); 
List<FileItem> items = fileUpload.parseRequest(req.raw()); 

// image is the field name that we want to save 
FileItem item = items.stream() 
       .filter(e -> "image".equals(e.getFieldName())) 
       .findFirst().get(); 
String fileName = item.getName(); 
item.write(new File(dir, fileName)); 
halt(200); 
return null; 
}); 

Vedi https://github.com/perwendel/spark/issues/26#issuecomment-95077039

5

La risposta fornita da Kai Yao è corretto, tranne che quando si utilizza:

request.raw().setAttribute("org.eclipse.multipartConfig", multipartConfigElement); 

uso questo, invece:

request.raw().setAttribute("org.eclipse.jetty.multipartConfig", multipartConfigElement); 
+0

questo è quello che ha funzionato per me –

0

ho trovato qui esempio completo: https://github.com/tipsy/spark-file-upload/blob/master/src/main/java/UploadExample.java

import spark.*; 
import javax.servlet.*; 
import javax.servlet.http.*; 
import java.io.*; 
import java.nio.file.*; 
import static spark.Spark.*; 
import static spark.debug.DebugScreen.*; 

public class UploadExample { 

    public static void main(String[] args) { 
     enableDebugScreen(); 

     File uploadDir = new File("upload"); 
     uploadDir.mkdir(); // create the upload directory if it doesn't exist 

     staticFiles.externalLocation("upload"); 

     get("/", (req, res) -> 
        "<form method='post' enctype='multipart/form-data'>" // note the enctype 
       + " <input type='file' name='uploaded_file' accept='.png'>" // make sure to call getPart using the same "name" in the post 
       + " <button>Upload picture</button>" 
       + "</form>" 
     ); 

     post("/", (req, res) -> { 

      Path tempFile = Files.createTempFile(uploadDir.toPath(), "", ""); 

      req.attribute("org.eclipse.jetty.multipartConfig", new MultipartConfigElement("/temp")); 

      try (InputStream input = req.raw().getPart("uploaded_file").getInputStream()) { // getPart needs to use same "name" as input field in form 
       Files.copy(input, tempFile, StandardCopyOption.REPLACE_EXISTING); 
      } 

      logInfo(req, tempFile); 
      return "<h1>You uploaded this image:<h1><img src='" + tempFile.getFileName() + "'>"; 

     }); 

    } 

    // methods used for logging 
    private static void logInfo(Request req, Path tempFile) throws IOException, ServletException { 
     System.out.println("Uploaded file '" + getFileName(req.raw().getPart("uploaded_file")) + "' saved as '" + tempFile.toAbsolutePath() + "'"); 
    } 

    private static String getFileName(Part part) { 
     for (String cd : part.getHeader("content-disposition").split(";")) { 
      if (cd.trim().startsWith("filename")) { 
       return cd.substring(cd.indexOf('=') + 1).trim().replace("\"", ""); 
      } 
     } 
     return null; 
    } 

} 

Si prega di notare che in questo esempio per iterare su tutti i file utilizzare javax.servlet.http.HttpServletRequest#getParts. Anche in questo esempio invece di analizzare il nome del file puoi semplicemente farlo usando javax.servlet.http.Part#getSubmittedFileName. E non dimenticare di chiudere il flusso che ottieni. E anche eliminare il file utilizzando javax.servlet.http.Part#delete se necessario

+0

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - [Dalla recensione] (/ recensione/post di bassa qualità/17188595) – rafalmp

Problemi correlati