首先,不要在原始文件中使用ServletHandler。
这是ServletContextHandler 的内部类,不能直接使用。
接下来,使用ServletContextHandler 适当地拥有一个您的servlet 可以使用的健全的javax.servlet.ServletContext。
当您将FileUploadServlet 添加到ServletContextHandler 时,请在此时声明MultipartConfigElement。
例子:
package jetty.multipart;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.MultiPartFormDataCompliance;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import static java.nio.charset.StandardCharsets.UTF_8;
public class SOFileUploadDemo
{
public static void main(String[] args) throws Exception
{
Server server = new Server();
HttpConfiguration httpConf = new HttpConfiguration();
// Use the standard parser for multipart/mime
httpConf.setMultiPartFormDataCompliance(MultiPartFormDataCompliance.RFC7578);
// Establish the HTTP ServerConnector
ServerConnector httpConnector = new ServerConnector(server, new HttpConnectionFactory(httpConf));
httpConnector.setPort(8080);
server.addConnector(httpConnector);
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
contextHandler.setContextPath("/");
// Establish output directory
Path outputDir = Paths.get("target/upload-dir");
ensureDirExists(outputDir);
ServletHolder uploadHolder = new ServletHolder(new FileUploadServlet(outputDir));
// MultiPartConfig setup - to allow for ServletRequest.getParts() usage
Path multipartTmpDir = Paths.get("target/multipart-tmp");
ensureDirExists(multipartTmpDir);
String location = multipartTmpDir.toString();
long maxFileSize = 10 * 1024 * 1024; // 10 MB
long maxRequestSize = 10 * 1024 * 1024; // 10 MB
int fileSizeThreshold = 64 * 1024; // 64 KB
MultipartConfigElement multipartConfig = new MultipartConfigElement(location, maxFileSize, maxRequestSize, fileSizeThreshold);
uploadHolder.getRegistration().setMultipartConfig(multipartConfig);
contextHandler.addServlet(uploadHolder, "/upload/*");
server.setHandler(contextHandler);
server.start();
System.out.println("You can find the server at " + server.getURI());
server.join();
}
private static Path ensureDirExists(Path path) throws IOException
{
Path dir = path.toAbsolutePath();
if (!Files.exists(dir))
{
Files.createDirectories(dir);
}
return dir;
}
public static class FileUploadServlet extends HttpServlet
{
private final Path outputDir;
public FileUploadServlet(Path outputDir)
{
this.outputDir = outputDir;
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
for (Part part : request.getParts())
{
out.printf("Got Part[%s].size=%s%n", part.getName(), part.getSize());
out.printf("Got Part[%s].contentType=%s%n", part.getName(), part.getContentType());
out.printf("Got Part[%s].submittedFileName=%s%n", part.getName(), part.getSubmittedFileName());
String filename = part.getSubmittedFileName();
if (StringUtil.isNotBlank(filename))
{
// ensure we don't have "/" and ".." in the raw form.
filename = URLEncoder.encode(filename, UTF_8);
Path outputFile = outputDir.resolve(filename);
try (InputStream inputStream = part.getInputStream();
OutputStream outputStream = Files.newOutputStream(outputFile, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING))
{
IO.copy(inputStream, outputStream);
out.printf("Saved Part[%s] to %s%n", part.getName(), outputFile.toString());
}
}
}
}
}
}
如果您运行该代码并使用curl 对其进行测试,您会得到...
$ curl -v -F key1=value1 -F upload=@image.png http://localhost:8080/upload/
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> POST /upload/ HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 130684
> Content-Type: multipart/form-data; boundary=------------------------4a0d7cd4df695240
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Date: Tue, 23 Jun 2020 14:22:17 GMT
< Content-Type: text/plain;charset=utf-8
< Content-Length: 255
< Server: Jetty(9.4.30.v20200611)
<
Got Part[key1].size=6
Got Part[key1].contentType=null
Got Part[key1].submittedFileName=null
Got Part[upload].size=130397
Got Part[upload].contentType=image/png
Got Part[upload].submittedFileName=image.png
Saved Part[upload] to target/upload-dir/image.png
* Connection #0 to host localhost left intact
你可以看到target/upload-dir产生的文件
$ ls -la target/upload-dir/
total 136
drwxrwxr-x 2 joakim joakim 4096 Jun 23 09:22 ./
drwxrwxr-x 8 joakim joakim 4096 Jun 23 09:20 ../
-rw-rw-r-- 1 joakim joakim 130397 Jun 23 09:22 image.png