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"));
        }
Example #2
0
        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>());
        }
Example #3
0
        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"));
        }
Example #4
0
        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
            }));
        }
Example #6
0
        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>());
        }