2015-03-31 120 views
10

我使用spark開發一個Web應用程序;當我想上傳一個文件時出現的問題:spark java:如何處理多部分/表單數據輸入?

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"; 
     }); 
    } 
} 

但我得到這個錯誤:

[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) 

即使我嘗試顯式地指定類型,如:

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

它仍然會失敗。

我大概可以找到一個庫來解析multipart/form-data,抓取整個內容並解析自己,但那會浪費。

我可以配置spark來處理這種情況嗎?

回答

4

通過加入幾行代碼添加到多的配置,你可以處理的multipart/form-data的,無需外部庫:

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 
} 

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

+0

如何將這樣的圖片上傳到src/main/resources,我可以訪問它? – 2016-04-25 02:22:59

4

我使用Apache的百科全書,文件上傳來處理這個問題。

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; 
}); 

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

5

由啓耀提供的答案是,除了正確使用時:

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

用這個代替:

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

這是我工作的那個 – 2016-07-14 15:08:18

0

我發現完整的例子在這裏: 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; 
    } 

} 

請注意,在此示例中,爲了遍歷所有文件,使用javax.servlet.http.HttpServletRequest#getParts。同樣在這個例子中,而不是解析文件名,你可以簡單地使用javax.servlet.http.Part#getSubmittedFileName。並且不要忘記關閉你得到的流。如果需要還可以使用javax.servlet.http.Part#delete刪除文件

+0

雖然這個鏈接可能回答這個問題,但最好在這裏包含答案的重要部分,並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 - [來自評論](/ review/low-quality-posts/17188595) – rafalmp 2017-08-30 13:11:01

相關問題