|
11 | 11 | import com.conveyal.gtfs.GTFSFeed;
|
12 | 12 | import com.fasterxml.jackson.databind.JsonNode;
|
13 | 13 | import com.fasterxml.jackson.databind.node.ArrayNode;
|
| 14 | +import com.google.common.io.ByteStreams; |
14 | 15 | import org.slf4j.Logger;
|
15 | 16 | import org.slf4j.LoggerFactory;
|
16 | 17 | import spark.Request;
|
17 | 18 | import spark.Response;
|
18 | 19 |
|
19 | 20 | import javax.servlet.MultipartConfigElement;
|
20 | 21 | import javax.servlet.ServletException;
|
| 22 | +import javax.servlet.ServletInputStream; |
| 23 | +import javax.servlet.ServletRequestWrapper; |
21 | 24 | import javax.servlet.http.HttpServletResponse;
|
22 | 25 | import javax.servlet.http.Part;
|
23 | 26 | import java.io.BufferedInputStream;
|
@@ -55,28 +58,26 @@ public class GtfsPlusController {
|
55 | 58 | private static FeedStore gtfsPlusStore = new FeedStore("gtfsplus");
|
56 | 59 |
|
57 | 60 |
|
58 |
| - public static Boolean uploadGtfsPlusFile (Request req, Response res) throws IOException, ServletException { |
59 |
| - |
60 |
| - //FeedSource s = FeedSource.retrieveById(req.queryParams("feedSourceId")); |
61 |
| - String feedVersionId = req.params("versionid"); |
62 |
| - |
63 |
| - if (req.raw().getAttribute("org.eclipse.jetty.multipartConfig") == null) { |
64 |
| - MultipartConfigElement multipartConfigElement = new MultipartConfigElement(System.getProperty("java.io.tmpdir")); |
65 |
| - req.raw().setAttribute("org.eclipse.jetty.multipartConfig", multipartConfigElement); |
66 |
| - } |
67 |
| - |
68 |
| - Part part = req.raw().getPart("file"); |
69 |
| - |
70 |
| - LOG.info("Saving GTFS+ feed {} from upload for version " + feedVersionId); |
71 |
| - |
72 |
| - |
73 |
| - InputStream uploadStream; |
| 61 | + private static Boolean uploadGtfsPlusFile (Request req, Response res) throws IOException, ServletException { |
74 | 62 | try {
|
75 |
| - uploadStream = part.getInputStream(); |
76 |
| - gtfsPlusStore.newFeed(feedVersionId, uploadStream, null); |
77 |
| - } catch (IOException e) { |
| 63 | + String feedVersionId = req.params("versionid"); |
| 64 | + File newGtfsFile = new File(gtfsPlusStore.getPathToFeed(feedVersionId)); |
| 65 | + // Bypass Spark's request wrapper which always caches the request body in memory that may be a very large |
| 66 | + // GTFS file. Also, the body of the request is the GTFS file instead of using multipart form data because |
| 67 | + // multipart form handling code also caches the request body. |
| 68 | + ServletInputStream inputStream = ((ServletRequestWrapper) req.raw()).getRequest().getInputStream(); |
| 69 | + FileOutputStream fileOutputStream = new FileOutputStream(newGtfsFile); |
| 70 | + // Guava's ByteStreams.copy uses a 4k buffer (no need to wrap output stream), but does not close streams. |
| 71 | + ByteStreams.copy(inputStream, fileOutputStream); |
| 72 | + fileOutputStream.close(); |
| 73 | + inputStream.close(); |
| 74 | + if (newGtfsFile.length() == 0) { |
| 75 | + throw new IOException("No file found in request body."); |
| 76 | + } |
| 77 | + LOG.info("Saving GTFS+ feed {} from upload for version " + feedVersionId); |
| 78 | + } catch (Exception e) { |
78 | 79 | LOG.error("Unable to open input stream from upload");
|
79 |
| - logMessageAndHalt(req, 400, "Unable to open input stream from upload", e); |
| 80 | + logMessageAndHalt(req, 500, "Unable to read uploaded GTFS+ file.", e); |
80 | 81 | }
|
81 | 82 |
|
82 | 83 | return true;
|
|
0 commit comments