我正在使用spark来开发Web应用程序;当我想上传文件时出现问题:
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,抓取整个内容并自己解析,但那是浪费。
我可以配置火花来处理这种情况吗?
答案 0 :(得分:6)
Kai Yao提供的答案是正确的,但使用时除外:
request.raw().setAttribute("org.eclipse.multipartConfig", multipartConfigElement);
改为使用:
request.raw().setAttribute("org.eclipse.jetty.multipartConfig", multipartConfigElement);
答案 1 :(得分:5)
我使用apache commons-fileupload来处理这个问题。
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
答案 2 :(得分:4)
通过添加几行代码来添加multipart配置,您可以在没有外部库的情况下处理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/
答案 3 :(得分:1)
我在这里找到完整的例子: 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
删除文件