11package com .conveyal .analysis .util ;
22
33import com .conveyal .analysis .AnalysisServerException ;
4- import com .conveyal .analysis .datasource .DataSourceException ;
54import com .conveyal .file .FileUtils ;
65import com .conveyal .r5 .util .ExceptionUtils ;
76import org .apache .commons .fileupload .FileItem ;
7+ import org .apache .commons .fileupload .disk .DiskFileItem ;
8+ import org .apache .commons .fileupload .disk .DiskFileItemFactory ;
89import org .apache .commons .fileupload .servlet .ServletFileUpload ;
910
1011import javax .servlet .http .HttpServletRequest ;
1112import java .io .File ;
12- import java .io .IOException ;
1313import java .io .UnsupportedEncodingException ;
1414import java .util .ArrayList ;
1515import java .util .List ;
@@ -30,8 +30,17 @@ public static Map<String, List<FileItem>> getRequestFiles (HttpServletRequest re
3030 // The Javadoc on this factory class doesn't say anything about thread safety. Looking at the source code it
3131 // all looks threadsafe. But also very lightweight to instantiate, so in this code run by multiple threads
3232 // we play it safe and always create a new factory.
33+ // Setting a size threshold of 0 causes all files to be written to disk, which allows processing them in a
34+ // uniform way in other threads, after the request handler has returned. This does however cause some very
35+ // small form fields to be written to disk files. Ideally we'd identify the smallest actual file we'll ever
36+ // handle and set the threshold a little higher. The downside is that if a tiny file is actually uploaded even
37+ // by accident, our code will not be able to get a file handle for it and fail. Some legitimate files like
38+ // Shapefile .prj sidecars can be really small.
39+ // If we always saved the FileItems via write() or read them with getInputStream() they would not all need to
40+ // be on disk.
3341 try {
34- ServletFileUpload sfu = new ServletFileUpload ();
42+ DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory (0 , null );
43+ ServletFileUpload sfu = new ServletFileUpload (diskFileItemFactory );
3544 return sfu .parseParameterMap (req );
3645 } catch (Exception e ) {
3746 throw AnalysisServerException .fileUpload (ExceptionUtils .stackTraceString (e ));
@@ -97,12 +106,11 @@ public static File storeFileItem(FileItem fileItem) {
97106 }
98107
99108 public static File storeFileItemInDirectory (FileItem fileItem , File directory ) {
100- try {
101- File file = new File (directory , fileItem .getName ());
102- fileItem .getInputStream ().transferTo (FileUtils .getOutputStream (file ));
103- return file ;
104- } catch (IOException e ) {
105- throw new DataSourceException (e .getMessage ());
109+ File file = new File (directory , fileItem .getName ());
110+ boolean renameSuccessful = ((DiskFileItem ) fileItem ).getStoreLocation ().renameTo (file );
111+ if (!renameSuccessful ) {
112+ throw AnalysisServerException .fileUpload ("Error storing file in directory on disk. File.renameTo() failed." );
106113 }
114+ return file ;
107115 }
108116}
0 commit comments