I am using code from the .net samples on streaming file uploads:
[HttpPost]
public async Task<IActionResult> Post()
{
var request = HttpContext.Request;
// validation of Content-Type
// 1. first, it must be a form-data request
// 2. a boundary should be found in the Content-Type
if (!request.HasFormContentType ||
!MediaTypeHeaderValue.TryParse(request.ContentType, out var mediaTypeHeader) ||
string.IsNullOrEmpty(mediaTypeHeader.Boundary.Value))
{
return new UnsupportedMediaTypeResult();
}
var reader = new MultipartReader(mediaTypeHeader.Boundary.Value, request.Body);
var section = await reader.ReadNextSectionAsync();
// This sample try to get the first file from request and save it
// Make changes according to your needs in actual use
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition,
out var contentDisposition);
if (hasContentDispositionHeader && contentDisposition.DispositionType.Equals("form-data") &&
!string.IsNullOrEmpty(contentDisposition.FileName.Value))
{
await _uploader.UploadAsync(section.Body);
return Ok();
}
section = await reader.ReadNextSectionAsync();
}
// If the code runs to this location, it means that no files have been saved
return BadRequest("No files data in the request.");
}
But the problem is I am able to upload a 20MB PDF. I want to reduce this to 5MB. Ideally I want to be able to set this per file extension.
The documentation I have read suggests adding this to my Startup:
var tenMB = 10485760;
services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = tenMB;
});
As I understand this is supposed to throw an invalid data exception, but it doesnt. It doesnt do anything.
What am I doing wrong here please? I dont think I can read the size of a stream without reading the stream into memory?
CodePudding user response:
insert this in Startup class or it will not work otherwise
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.Configure<FormOptions>(options => {
options.ValueLengthLimit = tenMB;
options.MultipartBodyLengthLimit = tenMB;
})
}
CodePudding user response:
I believe the only way to do this is at the time of reading the stream. I achieved this with a buffer to improve performance (less reads) and a running count for how many bytes have been moved from the TCP stream to the file system. If it becomes too large the stream stops and the partial upload is deleted from the file system.
var maxFileSizeBytes = _settings.MaxUploadSize;
long totalBytesRead = 0;
while (true)
{
byte[] buffer = new byte[Kilobytes.Eight];
int bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0)
break;
totalBytesRead = bytesRead;
if (totalBytesRead > maxFileSizeBytes)
{
DeleteFile(fileName, outputStream);
throw UploadRejectedException.FileTooLarge(maxFileSizeBytes);
}
await outputStream.WriteAsync(buffer, 0, bytesRead);
}