public async Task <ResponseModel> Handle(MultipleFileUploadCommand request, CancellationToken cancellationToken) { var errorModel = new FormFileErrorModel(); if (!MultipartRequestHelper.IsMultipartContentType(_accessor.HttpContext.Request.ContentType)) { errorModel.Errors.Add("File", $"The request couldn't be processed (Error 1)."); return(ResponseProvider.Ok(errorModel)); } var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(_accessor.HttpContext.Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, _accessor.HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(cancellationToken); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse( section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { if (!MultipartRequestHelper .HasFileContentDisposition(contentDisposition)) { errorModel.Errors.Add("File", $"The request couldn't be processed (Error 2)."); return(ResponseProvider.Ok(errorModel)); } else { var streamedFileContent = await FileHelpers.ProcessStreamedFile( section, contentDisposition, errorModel, _permittedExtensions, _streamFileLimitSize, ValidateExtension.Encrypt); if (errorModel.Errors.Any()) { return(ResponseProvider.Ok(errorModel)); } var fileName = FileHelpers.GetFileName(section.ContentDisposition); var fileNameWithEncryptExtension = UploadFileHelper.GetFileNameWithEncryptExtension(fileName, request.EncryptAlg); var uploadFileAbsolutePath = UploadFileHelper.GetUploadAbsolutePath(_contentRootPath, fileNameWithEncryptExtension, request.Archive); await UploadFile(streamedFileContent, uploadFileAbsolutePath, request.EncryptAlg); } } section = await reader.ReadNextSectionAsync(cancellationToken); } return(ResponseProvider.Ok("Upload file successfully")); }
public static async Task <byte[]> ProcessStreamedFile( MultipartSection section, ContentDispositionHeaderValue contentDisposition, FormFileErrorModel errorModel, string[] permittedExtensions, long sizeLimit, ValidateExtension purpose) { try { using (var memoryStream = new MemoryStream()) { await section.Body.CopyToAsync(memoryStream); // Check if the file is empty or exceeds the size limit. if (memoryStream.Length == 0) { errorModel.Errors.Add("File", "The file is empty."); } else if (memoryStream.Length > sizeLimit) { var megabyteSizeLimit = sizeLimit / 1048576; errorModel.Errors.Add("File", $"The file exceeds {megabyteSizeLimit:N1} MB."); } else if (purpose == ValidateExtension.Encrypt && !IsValidFileExtensionAndSignature( contentDisposition.FileName.Value, memoryStream, permittedExtensions)) { errorModel.Errors.Add("File", "The file type isn't permitted or the file's " + "signature doesn't match the file's extension."); } else if (purpose == ValidateExtension.Decrypt && !IsValidFileExtensionForDecrypt( contentDisposition.FileName.Value, memoryStream, permittedExtensions)) { errorModel.Errors.Add("File", "The file type isn't permitted or the file's " + "signature doesn't match the file's extension."); } else { return(memoryStream.ToArray()); } } } catch (Exception ex) { errorModel.Errors.Add("File", "The upload failed. Please contact the Help Desk " + $" for support. Error: {ex.HResult}"); } return(Array.Empty <byte>()); }
public async Task <ResponseModel> Handle(BufferedMultipleFileUploadPhysicalCommand request, CancellationToken cancellationToken) { var errorModel = new FormFileErrorModel(); foreach (var formFile in request.Files) { var formFileContent = await FileHelpers .ProcessFormFile <BufferedMultipleFileUploadPhysical>( formFile, errorModel, _permittedExtensions, _defaultFileSizeLimit); if (errorModel.Errors.Any()) { return(ResponseProvider.Ok(errorModel)); } // For the file name of the uploaded file stored // server-side, use Path.GetRandomFileName to generate a safe // random file name. var filePath = UploadFileHelper.GetUploadAbsolutePath(_contentRootPath, formFile.FileName, request.Archive); //var trustedFileNameForFileStorage = Path.GetRandomFileName(); //var filePath = Path.Combine( // _targetFilePath, trustedFileNameForFileStorage); // **WARNING!** // In the following example, the file is saved without // scanning the file's contents. In most production // scenarios, an anti-virus/anti-malware scanner API // is used on the file before making the file available // for download or for use by other systems. // For more information, see the topic that accompanies // this sample. using (var fileStream = File.Create(filePath)) { await fileStream.WriteAsync(formFileContent, cancellationToken); // To work directly with the FormFiles, use the following // instead: //await formFile.CopyToAsync(fileStream); } } return(ResponseProvider.Ok("Upload file successful")); }
public async Task <ResponseModel> Handle(BufferedSingleFileUploadPhysicalCommand request, CancellationToken cancellationToken) { var errorModel = new FormFileErrorModel(); var formFileContent = await FileHelpers.ProcessFormFile <BufferedSingleFileUploadPhysical>( request.File, errorModel, _permittedExtensions, _defaultFileSizeLimit); if (errorModel.Errors.Any()) { return(ResponseProvider.Ok(errorModel)); } var filePath = UploadFileHelper.GetUploadAbsolutePath(_contentRootPath, request.File.FileName, request.Archive); using (var fileStream = File.Create(filePath)) { await fileStream.WriteAsync(formFileContent, cancellationToken); } return(ResponseProvider.Ok("Upload file successful")); }
public async Task <ResponseModel <SingleUploadResponse> > Handle(SingleFileUploadPhysicalCommand request, CancellationToken cancellationToken) { var swTotalEncrypt = new Stopwatch(); swTotalEncrypt.Start(); var errorModel = new FormFileErrorModel(); var multiPartContentTypeValidation = MultiPartContentTypeValidation(_accessor.HttpContext.Request.ContentType) .Select(x => x.ErrorMessage) .ToArray(); if (multiPartContentTypeValidation.Any()) { return(ResponseProvider.BadRequest <SingleUploadResponse>(multiPartContentTypeValidation)); } var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(_accessor.HttpContext.Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, _accessor.HttpContext.Request.Body); var section = await reader.ReadNextSectionAsync(cancellationToken); while (section != null) { var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse( section.ContentDisposition, out var contentDisposition); if (hasContentDispositionHeader) { var hasFileContentDispositionValidation = HasFileContentDispositionValidation(contentDisposition) .Select(x => x.ErrorMessage) .ToArray(); if (hasFileContentDispositionValidation.Any()) { return(ResponseProvider.BadRequest <SingleUploadResponse>(hasFileContentDispositionValidation)); } else { var streamedFileContent = await FileHelpers.ProcessStreamedFile( section, contentDisposition, errorModel, _permittedExtensions, _streamFileLimitSize, ValidateExtension.Encrypt); if (errorModel.Errors.Any()) { //return ResponseProvider.BadRequest<SingleUploadResponse>(errorModel.Errors); return(ResponseProvider.Ok(new SingleUploadResponse())); } var fileNameWithEncryptExtension = UploadFileHelper.GetFileNameWithEncryptExtension(request.File.FileName, request.EncryptAlg); var uploadFileAbsolutePath = UploadFileHelper.GetUploadAbsolutePath(_contentRootPath, fileNameWithEncryptExtension, request.Archive); await UploadFile(streamedFileContent, uploadFileAbsolutePath, request.EncryptAlg); } } section = await reader.ReadNextSectionAsync(cancellationToken); } swTotalEncrypt.Stop(); var requestScheme = _accessor.HttpContext.Request.Scheme; var domain = _accessor.HttpContext.Request.Host.Value; var url = Path.Combine(requestScheme, domain, "Archive", request.Archive.ToString(), request.File.FileName); Console.Write($"File length: {request.File.Length / 1024f / 1024f} MB"); Console.WriteLine($"Encrypt time: {swTotalEncrypt.ElapsedMilliseconds}"); return(ResponseProvider.Ok(new SingleUploadResponse { Url = url })); }
public static async Task <byte[]> ProcessFormFile <T>(IFormFile formFile, FormFileErrorModel errorModel, string[] permittedExtensions, long sizeLimit) { var fieldDisplayName = string.Empty; // Use reflection to obtain the display name for the model // property associated with this IFormFile. If a display // name isn't found, error messages simply won't show // a display name. MemberInfo property = typeof(T).GetProperty( formFile.Name.Substring(formFile.Name.IndexOf(".", StringComparison.Ordinal) + 1)); if (property != null && property.GetCustomAttribute(typeof(DisplayAttribute)) is DisplayAttribute displayAttribute) { fieldDisplayName = $"{displayAttribute.Name} "; } // Don't trust the file name sent by the client. To display // the file name, HTML-encode the value. var trustedFileNameForDisplay = WebUtility.HtmlEncode(formFile.FileName); // Check the file length. This check doesn't catch files that only have // a BOM as their content. if (formFile.Length == 0) { errorModel.Errors.Add(formFile.Name, $"{fieldDisplayName}({trustedFileNameForDisplay}) is empty."); return(Array.Empty <byte>()); } if (formFile.Length > sizeLimit) { var megabyteSizeLimit = sizeLimit / 1048576; errorModel.Errors.Add(formFile.Name, $"{fieldDisplayName}({trustedFileNameForDisplay}) exceeds " + $"{megabyteSizeLimit:N1} MB."); return(Array.Empty <byte>()); } try { using (var memoryStream = new MemoryStream()) { await formFile.CopyToAsync(memoryStream); // Check the content length in case the file's only // content was a BOM and the content is actually // empty after removing the BOM. if (memoryStream.Length == 0) { errorModel.Errors.Add(formFile.Name, $"{fieldDisplayName}({trustedFileNameForDisplay}) is empty."); } if (!IsValidFileExtensionAndSignature(formFile.FileName, memoryStream, permittedExtensions)) { errorModel.Errors.Add(formFile.Name, $"{fieldDisplayName}({trustedFileNameForDisplay}) file " + "type isn't permitted or the file's signature " + "doesn't match the file's extension."); } else { return(memoryStream.ToArray()); } } } catch (Exception ex) { errorModel.Errors.Add(formFile.Name, $"{fieldDisplayName}({trustedFileNameForDisplay}) upload failed. " + $"Please contact the Help Desk for support. Error: {ex.HResult}"); } return(Array.Empty <byte>()); }