Skip to content

Commit

Permalink
Ensure Synchronoss temp directories do not collide
Browse files Browse the repository at this point in the history
This commit makes sure that Synchronoss uses a random temporary
directory to store uploaded files, so that two instances do not collide.

Closes gh-26931
  • Loading branch information
poutsma committed May 11, 2021
1 parent 1469bdb commit cce60c4
Showing 1 changed file with 38 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,11 +17,13 @@
package org.springframework.http.codec.multipart;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
Expand Down Expand Up @@ -78,12 +80,16 @@
*/
public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implements HttpMessageReader<Part> {

private static final String FILE_STORAGE_DIRECTORY_PREFIX = "synchronoss-file-upload-";

private int maxInMemorySize = 256 * 1024;

private long maxDiskUsagePerPart = -1;

private int maxParts = -1;

private Path fileStorageDirectory = createTempDirectory();


/**
* Configure the maximum amount of memory that is allowed to use per part.
Expand Down Expand Up @@ -144,6 +150,22 @@ public int getMaxParts() {
return this.maxParts;
}

/**
* Set the directory used to store parts larger than
* {@link #setMaxInMemorySize(int) maxInMemorySize}. By default, a new
* temporary directory is created.
* @throws IOException if an I/O error occurs, or the parent directory
* does not exist
* @since 5.3.7
*/
public void setFileStorageDirectory(Path fileStorageDirectory) throws IOException {
Assert.notNull(fileStorageDirectory, "FileStorageDirectory must not be null");
if (!Files.exists(fileStorageDirectory)) {
Files.createDirectory(fileStorageDirectory);
}
this.fileStorageDirectory = fileStorageDirectory;
}


@Override
public List<MediaType> getReadableMediaTypes() {
Expand All @@ -167,7 +189,7 @@ public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType

@Override
public Flux<Part> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints) {
return Flux.create(new SynchronossPartGenerator(message))
return Flux.create(new SynchronossPartGenerator(message, this.fileStorageDirectory))
.doOnNext(part -> {
if (!Hints.isLoggingSuppressed(hints)) {
LogFormatUtils.traceDebug(logger, traceOn -> Hints.getLogPrefix(hints) + "Parsed " +
Expand All @@ -183,6 +205,15 @@ public Mono<Part> readMono(ResolvableType elementType, ReactiveHttpInputMessage
return Mono.error(new UnsupportedOperationException("Cannot read multipart request body into single Part"));
}

private static Path createTempDirectory() {
try {
return Files.createTempDirectory(FILE_STORAGE_DIRECTORY_PREFIX);
}
catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}


/**
* Subscribe to the input stream and feed the Synchronoss parser. Then listen
Expand All @@ -194,14 +225,17 @@ private class SynchronossPartGenerator extends BaseSubscriber<DataBuffer> implem

private final LimitedPartBodyStreamStorageFactory storageFactory = new LimitedPartBodyStreamStorageFactory();

private final Path fileStorageDirectory;

@Nullable
private NioMultipartParserListener listener;

@Nullable
private NioMultipartParser parser;

public SynchronossPartGenerator(ReactiveHttpInputMessage inputMessage) {
public SynchronossPartGenerator(ReactiveHttpInputMessage inputMessage, Path fileStorageDirectory) {
this.inputMessage = inputMessage;
this.fileStorageDirectory = fileStorageDirectory;
}

@Override
Expand All @@ -218,6 +252,7 @@ public void accept(FluxSink<Part> sink) {

this.parser = Multipart
.multipart(context)
.saveTemporaryFilesTo(this.fileStorageDirectory.toString())
.usePartBodyStreamStorageFactory(this.storageFactory)
.forNIO(this.listener);

Expand Down

0 comments on commit cce60c4

Please sign in to comment.