|
24 | 24 | import org.labkey.api.audit.provider.FileSystemAuditProvider; |
25 | 25 | import org.labkey.api.collections.CollectionUtils; |
26 | 26 | import org.labkey.api.data.Container; |
| 27 | +import org.labkey.api.data.TableViewForm; |
27 | 28 | import org.labkey.api.exp.ExperimentException; |
28 | 29 | import org.labkey.api.exp.api.ExpProtocol; |
29 | 30 | import org.labkey.api.pipeline.PipeRoot; |
|
40 | 41 | import java.io.IOException; |
41 | 42 | import java.io.InputStream; |
42 | 43 | import java.util.ArrayDeque; |
| 44 | +import java.util.ArrayList; |
| 45 | +import java.util.Collections; |
43 | 46 | import java.util.Deque; |
| 47 | +import java.util.HashMap; |
44 | 48 | import java.util.HashSet; |
45 | | -import java.util.Iterator; |
46 | 49 | import java.util.List; |
47 | 50 | import java.util.Map; |
48 | 51 | import java.util.Set; |
@@ -229,72 +232,84 @@ public String getFileName(MultipartFile file) |
229 | 232 |
|
230 | 233 | public Map<String, FileLike> savePostedFiles(ContextType context, @NotNull Set<String> parameterNames, boolean allowMultiple, boolean ensureExpData) throws ExperimentException, IOException |
231 | 234 | { |
| 235 | + if (!(context.getRequest() instanceof MultipartHttpServletRequest multipartRequest)) |
| 236 | + return Collections.emptyMap(); |
| 237 | + |
232 | 238 | Map<String, FileLike> files = CollectionUtils.enforceValueClass(new TreeMap<>(), FileLike.class); |
233 | 239 | Set<String> originalFileNames = new HashSet<>(); |
234 | | - if (context.getRequest() instanceof MultipartHttpServletRequest multipartRequest) |
| 240 | + Map<String, String> encodedParameterNames = new HashMap<>(); |
| 241 | + for (String parameterName : parameterNames) |
| 242 | + encodedParameterNames.put(TableViewForm.getMultiPartFormFieldNameForColumn(parameterName), parameterName); |
| 243 | + |
| 244 | + Deque<FileLike> overflowFiles = new ArrayDeque<>(); // using a deque for easy removal of single elements |
| 245 | + Set<String> unusedParameterNames = new HashSet<>(parameterNames); |
| 246 | + List<FileSystemAuditProvider.FileSystemAuditEvent> auditEvents = new ArrayList<>(); |
| 247 | + |
| 248 | + for (Map.Entry<String, List<MultipartFile>> entry : multipartRequest.getMultiFileMap().entrySet()) |
235 | 249 | { |
236 | | - Iterator<Map.Entry<String, List<MultipartFile>>> iter = multipartRequest.getMultiFileMap().entrySet().iterator(); |
237 | | - Deque<FileLike> overflowFiles = new ArrayDeque<>(); // using a deque for easy removal of single elements |
238 | | - Set<String> unusedParameterNames = new HashSet<>(parameterNames); |
239 | | - while (iter.hasNext()) |
| 250 | + if (!(encodedParameterNames.containsKey(entry.getKey()) || parameterNames.contains(entry.getKey()))) |
| 251 | + continue; |
| 252 | + |
| 253 | + boolean isAfterFirstFile = false; |
| 254 | + for (MultipartFile multipartFile : entry.getValue()) |
240 | 255 | { |
241 | | - Map.Entry<String, List<MultipartFile>> entry = iter.next(); |
242 | | - if (parameterNames.contains(entry.getKey())) |
| 256 | + String fileName = getFileName(multipartFile); |
| 257 | + if (!fileName.isEmpty() && !originalFileNames.add(fileName)) |
| 258 | + throw new ExperimentException("The file '" + fileName + " ' was uploaded twice - all files must be unique"); |
| 259 | + |
| 260 | + if (multipartFile.isEmpty()) |
| 261 | + continue; |
| 262 | + |
| 263 | + FileLike dir = getFileTargetDir(context); |
| 264 | + FileLike file = FileUtil.findUniqueFileName(fileName, dir); |
| 265 | + multipartFile.transferTo(toFileForWrite(file)); |
| 266 | + if (!dir.toURI().getPath().contains(TEMP_DIR_NAME)) |
243 | 267 | { |
244 | | - List<MultipartFile> multipartFiles = entry.getValue(); |
245 | | - boolean isAfterFirstFile = false; |
246 | | - for (MultipartFile multipartFile : multipartFiles) |
247 | | - { |
248 | | - String fileName = getFileName(multipartFile); |
249 | | - if (!fileName.isEmpty() && !originalFileNames.add(fileName)) |
250 | | - { |
251 | | - throw new ExperimentException("The file '" + fileName + " ' was uploaded twice - all files must be unique"); |
252 | | - } |
253 | | - if (!multipartFile.isEmpty()) |
254 | | - { |
255 | | - FileLike dir = getFileTargetDir(context); |
256 | | - FileLike file = FileUtil.findUniqueFileName(fileName, dir); |
257 | | - multipartFile.transferTo(toFileForWrite(file)); |
258 | | - if (!dir.toURI().getPath().contains(TEMP_DIR_NAME)) |
259 | | - { |
260 | | - FileSystemAuditProvider.FileSystemAuditEvent event = new FileSystemAuditProvider.FileSystemAuditEvent(context.getContainer(), allowMultiple ? "File field provided for assay import" : "Primary file provided for assay import"); |
261 | | - event.setProvidedFileName(fileName); |
262 | | - event.setFile(file.getName()); |
263 | | - event.setDirectory(dir.toURI().getPath()); |
264 | | - AuditLogService.get().addEvent(context.getUser(), event); |
265 | | - } |
266 | | - if (!isAfterFirstFile) // first file gets stored with multipartFile's name |
267 | | - { |
268 | | - files.put(multipartFile.getName(), file); |
269 | | - isAfterFirstFile = true; |
270 | | - unusedParameterNames.remove(multipartFile.getName()); |
271 | | - } |
272 | | - else // other files get stored in leftover keys later to store only one file per key (bit of a hack) |
273 | | - { |
274 | | - overflowFiles.add(file); |
275 | | - } |
276 | | - |
277 | | - if (ensureExpData) |
278 | | - AbstractQueryUpdateService.ensureExpData(context.getUser(), context.getContainer(), toFileForWrite(file)); |
279 | | - } |
280 | | - } |
| 268 | + FileSystemAuditProvider.FileSystemAuditEvent event = new FileSystemAuditProvider.FileSystemAuditEvent(context.getContainer(), allowMultiple ? "File field provided for assay import" : "Primary file provided for assay import"); |
| 269 | + event.setProvidedFileName(fileName); |
| 270 | + event.setFile(file.getName()); |
| 271 | + event.setDirectory(dir.toURI().getPath()); |
| 272 | + auditEvents.add(event); |
281 | 273 | } |
282 | | - } |
283 | | - // now process overflow files, if any |
284 | | - for (String unusedParameterName : unusedParameterNames) |
285 | | - { |
286 | | - if (overflowFiles.isEmpty()) |
287 | | - break; // we're done |
288 | | - else |
| 274 | + if (!isAfterFirstFile) // first file gets stored with multipartFile's name |
289 | 275 | { |
290 | | - files.put(unusedParameterName, overflowFiles.remove()); |
| 276 | + String name = multipartFile.getName(); |
| 277 | + String param = encodedParameterNames.get(name); |
| 278 | + if (param == null && parameterNames.contains(name)) |
| 279 | + param = name; |
| 280 | + if (param == null) |
| 281 | + throw new ExperimentException("No parameter name found for multipart file '" + name + "'"); |
| 282 | + |
| 283 | + files.put(param, file); |
| 284 | + isAfterFirstFile = true; |
| 285 | + unusedParameterNames.remove(param); |
291 | 286 | } |
| 287 | + else // other files get stored in leftover keys later to store only one file per key (bit of a hack) |
| 288 | + { |
| 289 | + overflowFiles.add(file); |
| 290 | + } |
| 291 | + |
| 292 | + if (ensureExpData) |
| 293 | + AbstractQueryUpdateService.ensureExpData(context.getUser(), context.getContainer(), toFileForWrite(file)); |
292 | 294 | } |
| 295 | + } |
| 296 | + |
| 297 | + if (!auditEvents.isEmpty()) |
| 298 | + AuditLogService.get().addEvents(context.getUser(), auditEvents); |
293 | 299 |
|
294 | | - if (!overflowFiles.isEmpty() && !allowMultiple) // too many files; shouldn't happen, but if it does, throw an error |
295 | | - throw new ExperimentException("Tried to save too many files: number of keys is " + parameterNames.size() + |
296 | | - ", but " + overflowFiles.size() + " extra file(s) were found."); |
| 300 | + // now process overflow files, if any |
| 301 | + for (String unusedParameterName : unusedParameterNames) |
| 302 | + { |
| 303 | + if (overflowFiles.isEmpty()) |
| 304 | + break; // we're done |
| 305 | + |
| 306 | + files.put(unusedParameterName, overflowFiles.remove()); |
297 | 307 | } |
| 308 | + |
| 309 | + if (!overflowFiles.isEmpty() && !allowMultiple) // too many files; shouldn't happen, but if it does, throw an error |
| 310 | + throw new ExperimentException("Tried to save too many files: number of keys is " + parameterNames.size() + |
| 311 | + ", but " + overflowFiles.size() + " extra file(s) were found."); |
| 312 | + |
298 | 313 | return files; |
299 | 314 | } |
300 | 315 |
|
|
0 commit comments