diff --git a/src/Microsoft.AspNet.Http/BufferingHelper.cs b/src/Microsoft.AspNet.Http/BufferingHelper.cs index 3335203e29..47b08915c4 100644 --- a/src/Microsoft.AspNet.Http/BufferingHelper.cs +++ b/src/Microsoft.AspNet.Http/BufferingHelper.cs @@ -12,21 +12,30 @@ namespace Microsoft.AspNet.Http.Internal { internal const int DefaultBufferThreshold = 1024 * 30; + private readonly static Func _getTempDirectory = () => TempDirectory; + + private static string _tempDirectory; + public static string TempDirectory { get { - // Look for folders in the following order. - var temp = Environment.GetEnvironmentVariable("ASPNET_TEMP") ?? // ASPNET_TEMP - User set temporary location. - Path.GetTempPath(); // Fall back. - - if (!Directory.Exists(temp)) + if (_tempDirectory == null) { - // TODO: ??? - throw new DirectoryNotFoundException(temp); + // Look for folders in the following order. + var temp = Environment.GetEnvironmentVariable("ASPNET_TEMP") ?? // ASPNET_TEMP - User set temporary location. + Path.GetTempPath(); // Fall back. + + if (!Directory.Exists(temp)) + { + // TODO: ??? + throw new DirectoryNotFoundException(temp); + } + + _tempDirectory = temp; } - return temp; + return _tempDirectory; } } @@ -37,7 +46,7 @@ namespace Microsoft.AspNet.Http.Internal { // TODO: Register this buffer for disposal at the end of the request to ensure the temp file is deleted. // Otherwise it won't get deleted until GC closes the stream. - request.Body = new FileBufferingReadStream(body, bufferThreshold, TempDirectory); + request.Body = new FileBufferingReadStream(body, bufferThreshold, _getTempDirectory); } return request; } diff --git a/src/Microsoft.AspNet.WebUtilities/FileBufferingReadStream.cs b/src/Microsoft.AspNet.WebUtilities/FileBufferingReadStream.cs index b6df361dc4..9bed427578 100644 --- a/src/Microsoft.AspNet.WebUtilities/FileBufferingReadStream.cs +++ b/src/Microsoft.AspNet.WebUtilities/FileBufferingReadStream.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -18,7 +19,8 @@ namespace Microsoft.AspNet.WebUtilities { private readonly Stream _inner; private readonly int _memoryThreshold; - private readonly string _tempFileDirectory; + private string _tempFileDirectory; + private readonly Func _tempFileDirectoryAccessor; private Stream _buffer = new MemoryStream(); // TODO: We could have a more efficiently expanding buffer stream. private bool _inMemory = true; @@ -26,6 +28,17 @@ namespace Microsoft.AspNet.WebUtilities private bool _disposed; + // TODO: allow for an optional buffer size limit to prevent filling hard disks. 1gb? + public FileBufferingReadStream( + [NotNull] Stream inner, + int memoryThreshold, + [NotNull] Func tempFileDirectoryAccessor) + { + _inner = inner; + _memoryThreshold = memoryThreshold; + _tempFileDirectoryAccessor = tempFileDirectoryAccessor; + } + // TODO: allow for an optional buffer size limit to prevent filling hard disks. 1gb? public FileBufferingReadStream([NotNull] Stream inner, int memoryThreshold, [NotNull] string tempFileDirectory) { @@ -88,6 +101,13 @@ namespace Microsoft.AspNet.WebUtilities private Stream CreateTempFile() { + if (_tempFileDirectory == null) + { + Debug.Assert(_tempFileDirectoryAccessor != null); + _tempFileDirectory = _tempFileDirectoryAccessor(); + Debug.Assert(_tempFileDirectory != null); + } + var fileName = Path.Combine(_tempFileDirectory, "ASPNET_" + Guid.NewGuid().ToString() + ".tmp"); return new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete, 1024 * 16, FileOptions.Asynchronous | FileOptions.DeleteOnClose | FileOptions.SequentialScan);