public async Task <IActionResult> upload()
        {
            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                return(BadRequest($"Expected a multipart request, but got {Request.ContentType}"));
            }

            StringValues UserName;

            SiteConfig.HttpContextAccessor.HttpContext.Request.Headers.TryGetValue("UName", out UserName);

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var formAccumulator = new KeyValueAccumulator();
            // string targetFilePath = null;

            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(Request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);

            var reader = new MultipartReader(boundary, HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            var uploadPath = SiteConfig.Environment.ContentRootPath + UtilityBLL.ParseUsername(DirectoryPaths.UserVideosDefaultDirectoryPath, UserName.ToString());

            if (!Directory.Exists(uploadPath))
            {
                Directory_Process.CreateRequiredDirectories(SiteConfig.Environment.ContentRootPath + UtilityBLL.ParseUsername(SystemDirectoryPaths.UserDirectory, UserName.ToString()));
            }

            /*if (!Directory.Exists(uploadPath))
             * {
             *  return Ok(new { jsonrpc = "2.0", result = "Error", fname = uploadPath, message = "Main Directory Not Exist" });
             * }
             *
             * if (!Directory.Exists(uploadPath + "default/"))
             * {
             *  return Ok(new { jsonrpc = "2.0", result = "Error", fname = uploadPath + "default/", message = "Default Directory Not Exist" });
             * }*/

            var fileName = "";

            try
            {
                while (section != null)
                {
                    ContentDispositionHeaderValue contentDisposition;
                    var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition,
                                                                                             out contentDisposition);

                    if (hasContentDispositionHeader)
                    {
                        if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                        {
                            var output = formAccumulator.GetResults();
                            var chunk  = "0";
                            foreach (var item in output)
                            {
                                if (item.Key == "name")
                                {
                                    fileName = item.Value;
                                }
                                else if (item.Key == "chunk")
                                {
                                    chunk = item.Value;
                                }
                            }

                            var Path = uploadPath + "" + fileName;
                            using (var fs = new FileStream(Path, chunk == "0" ? FileMode.Create : FileMode.Append))
                            {
                                await section.Body.CopyToAsync(fs);

                                fs.Flush();
                            }
                        }
                        else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                        {
                            var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                            var encoding = GetEncoding(section);
                            using (var streamReader = new StreamReader(
                                       section.Body,
                                       encoding,
                                       detectEncodingFromByteOrderMarks: true,
                                       bufferSize: 1024,
                                       leaveOpen: true))
                            {
                                // The value length limit is enforced by MultipartBodyLengthLimit
                                var value = await streamReader.ReadToEndAsync();

                                if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                                {
                                    value = String.Empty;
                                }
                                formAccumulator.Append(key.ToString(), value);

                                if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                                {
                                    throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                                }
                            }
                        }
                    }

                    var result = formAccumulator.GetResults();

                    // Drains any remaining section body that has not been consumed and
                    // reads the headers for the next section.
                    section = await reader.ReadNextSectionAsync();
                }
            }
            catch (Exception ex)
            {
                return(Ok(new { jsonrpc = "2.0", result = "Error", fname = uploadPath, message = ex.Message }));
            }


            string url       = VideoUrlConfig.Source_Video_Url(UserName.ToString()) + "/" + fileName;
            string fileType  = System.IO.Path.GetExtension(fileName);
            string fileIndex = fileName.Replace(fileType, "");

            return(Ok(new { jsonrpc = "2.0", result = "OK", fname = fileName, url = url, filetype = fileType, filename = fileName, fileIndex = fileIndex }));
        }
Example #2
0
        public static async Task <string> StreamFilesAsync(this HttpRequest request, string directory)
        {
            string result = "0";

            if (!UpFileValidation.IsMultipartContentType(request.ContentType))
            {
                throw new Exception($"Expected a multipart request, but got {request.ContentType}");
            }

            //用于累加请求中所有表单url编码的键值对数量。
            KeyValueAccumulator formAccumulator = new KeyValueAccumulator();
            //获取请求的ContentType并model化
            MediaTypeHeaderValue contentType = MediaTypeHeaderValue.Parse(request.ContentType);
            //表单默认的分界线最大长度
            int boundaryLength = _FormOptions.MultipartBoundaryLengthLimit;
            //验证并得到分界线
            var boundary = UpFileValidation.GetBoundary(contentType, boundaryLength);
            var reader   = new MultipartReader(boundary, request.Body);

            var section = await reader.ReadNextSectionAsync();//用于读取Http请求中的第一个section数据

            while (section != null)
            {
                ContentDispositionHeaderValue content;
                var isHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out content);

                if (isHeader)
                {
                    //文件数据处理
                    if (UpFileValidation.IsFormFile(content))
                    {
                        Dictionary <string, StringValues> dic = formAccumulator.GetResults();
                        string filepath      = dic["filepath"];
                        string fileMd5       = dic["fileMd5"];
                        string chunk         = dic["chunk"];
                        string chunks        = dic["chunks"];
                        string save_filepath = directory + "\\" + filepath + "\\" + fileMd5;
                        if (!Directory.Exists(save_filepath))
                        {
                            Directory.CreateDirectory(save_filepath);
                        }

                        var fileName = UpFileValidation.GetFileName(content);
                        //这个是每一次从Http请求的section中读出文件数据的大小,单位是Byte即字节,这里设置为1024的意思是,
                        //每次从Http请求的section数据流中读取出1024字节的数据到服务器内存中,然后写入下面targetFileStream的文件流中
                        //,可以根据服务器的内存大小调整这个值。这样就避免了一次加载所有上传文件的数据到服务器内存中,导致服务器崩溃。
                        var loadBufferBytes = 10 * 1024 * 1024;

                        using (var targetFileStream = System.IO.File.Create(save_filepath + "\\" + chunk))
                        {
                            await section.Body.CopyToAsync(targetFileStream, loadBufferBytes);

                            result = "1";
                        }
                    }
                    //额外表单参数处理
                    else if (UpFileValidation.IsFormData(content))
                    {
                        // 这里不要限制键名的长度,因为多部分头的长度限制已经生效。
                        var key      = HeaderUtilities.RemoveQuotes(content.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // 获取键的值
                            var value = await streamReader.ReadToEndAsync();

                            //如果值为undefined,则替换为空
                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key.Value, value);
                            //参数键值对不能大于默认数量,否则异常
                            if (formAccumulator.ValueCount > _FormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"键值对参数最大不能超过{ _FormOptions.ValueCountLimit}");
                            }
                        }
                    }
                }
                //用于读取Http请求中的下一个section数据
                section = await reader.ReadNextSectionAsync();
            }
            return(result);
        }
Example #3
0
        public async Task <IActionResult> StreamUpload()
        {
            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                return(BadRequest($"Expected a multipart request, but got {Request.ContentType}"));
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var    formAccumulator = new KeyValueAccumulator();
            string targetFilePath  = null;

            var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType),
                                                              _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary,
                                             HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition,
                                                                                         out contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        targetFilePath = Path.GetTempFileName();
                        using (var targetStream = System.IO.File.Create(targetFilePath)) {
                            await section.Body.CopyToAsync(targetStream);

                            //_logger.LogInformation( $"Copied the uploaded file '{targetFilePath}'" );
                        }
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(section.Body,
                                                                   encoding,
                                                                   detectEncodingFromByteOrderMarks: true,
                                                                   bufferSize: 1024,
                                                                   leaveOpen: true)) {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (String.Equals(value,
                                              "undefined",
                                              StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key,
                                                   value);

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new
                                      InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            // Bind form data to a model
            var requestedFileUpload = new FileUploadRequest();
            var formValueProvider   = new FormValueProvider(BindingSource.Form,
                                                            new FormCollection(formAccumulator.GetResults()),
                                                            CultureInfo.CurrentCulture);

            var bindingSuccessful = await TryUpdateModelAsync(requestedFileUpload,
                                                              prefix : "",
                                                              valueProvider : formValueProvider);

            if (!bindingSuccessful)
            {
                if (!ModelState.IsValid)
                {
                    return(BadRequest(ModelState));
                }
            }

            var uploadedData = new FileUploadRequestResult()
            {
                Name     = requestedFileUpload.Name,
                Age      = requestedFileUpload.Age,
                Zipcode  = requestedFileUpload.Zipcode,
                FilePath = targetFilePath
            };

            return(Json(uploadedData));
        }
Example #4
0
        /// <summary>
        /// Handle multi-part form data file streams.
        /// </summary>
        public static async Task <string> StreamFile(this HttpRequest request, string filename, ILogger log)
        {
            var    formAccumulator    = new KeyValueAccumulator();
            string targetFilePath     = null;
            var    defaultFormOptions = new FormOptions();

            // Boundary is required by the MultipartReader, but we'll auto generate one in the helper, it
            // doesn't need to be provided in the request header.
            var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(request.ContentType), defaultFormOptions.MultipartBoundaryLengthLimit);

            var reader  = new MultipartReader(boundary, request.Body);
            var section = await reader.ReadNextSectionAsync();

            log.LogDebug("Processing file stream...");

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
                var dispositionParameters       = contentDisposition.Parameters.Aggregate("", (current, parameter) => $"{current},{parameter}");
                log.LogDebug($"Processing section '{contentDisposition.DispositionType}:{dispositionParameters}'");

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        targetFilePath = Path.Combine(Path.GetTempPath(), filename);
                        log.LogDebug($"Writing stream to '{targetFilePath}'");

                        using (var targetStream = File.Create(targetFilePath))
                        {
                            await section.Body.CopyToAsync(targetStream);
                        }
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Do not limit the key name length here because the multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = section.GetEncoding();

                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = string.Empty;
                            }

                            formAccumulator.Append(key.ToString(), value);

                            if (formAccumulator.ValueCount > defaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            log.LogDebug("Completed processing request body.");

            return(targetFilePath);
        }
        public static async Task <FormValueProvider> StreamFile(this HttpRequest request, Func <FileMultipartSection, Stream> createStream)
        {
            if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType))
            {
                throw new Exception($"Expected a multipart request, but got {request.ContentType}");
            }

            // 把 request 中的 Form 依照 Key 及 Value 存到此物件
            var formAccumulator = new KeyValueAccumulator();

            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, request.Body);

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                // 把 Form 的欄位內容逐一取出
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        // 若此欄位是檔案,就寫入至 Stream;
                        using (var targetStream = createStream(section.AsFileSection()))
                        {
                            await section.Body.CopyToAsync(targetStream);
                        }
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // 若此欄位不是檔案,就把 Key 及 Value 取出,存入 formAccumulator
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name).Value;
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            var value = await streamReader.ReadToEndAsync();

                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key, value);

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // 取得 Form 的下一個欄位
                section = await reader.ReadNextSectionAsync();
            }

            // Bind form data to a model
            var formValueProvider = new FormValueProvider(
                BindingSource.Form,
                new FormCollection(formAccumulator.GetResults()),
                CultureInfo.CurrentCulture);

            return(formValueProvider);
        }
Example #6
0
        public async Task <IFormCollection> ReadFormAsync(CancellationToken cancellationToken)
        {
            if (Form != null)
            {
                return(Form);
            }

            if (!HasFormContentType)
            {
                throw new InvalidOperationException("Incorrect Content-Type: " + _request.ContentType);
            }

            cancellationToken.ThrowIfCancellationRequested();

            _request.EnableRewind();

            IDictionary <string, string[]> formFields = null;
            var files = new FormFileCollection();

            // Some of these code paths use StreamReader which does not support cancellation tokens.
            using (cancellationToken.Register(_request.HttpContext.Abort))
            {
                var contentType = ContentType;
                // Check the content-type
                if (HasApplicationFormContentType(contentType))
                {
                    var encoding = FilterEncoding(contentType.Encoding);
                    formFields = await FormReader.ReadFormAsync(_request.Body, encoding, cancellationToken);
                }
                else if (HasMultipartFormContentType(contentType))
                {
                    var formAccumulator = new KeyValueAccumulator <string, string>(StringComparer.OrdinalIgnoreCase);

                    var boundary        = GetBoundary(contentType);
                    var multipartReader = new MultipartReader(boundary, _request.Body);
                    var section         = await multipartReader.ReadNextSectionAsync(cancellationToken);

                    while (section != null)
                    {
                        var headers = new HeaderDictionary(section.Headers);
                        ContentDispositionHeaderValue contentDisposition;
                        ContentDispositionHeaderValue.TryParse(headers.Get(HeaderNames.ContentDisposition), out contentDisposition);
                        if (HasFileContentDisposition(contentDisposition))
                        {
                            // Find the end
                            await section.Body.DrainAsync(cancellationToken);

                            var file = new FormFile(_request.Body, section.BaseStreamOffset.Value, section.Body.Length)
                            {
                                Headers = headers,
                            };
                            files.Add(file);
                        }
                        else if (HasFormDataContentDisposition(contentDisposition))
                        {
                            // Content-Disposition: form-data; name="key"
                            //
                            // value

                            var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                            MediaTypeHeaderValue mediaType;
                            MediaTypeHeaderValue.TryParse(headers.Get(HeaderNames.ContentType), out mediaType);
                            var encoding = FilterEncoding(mediaType?.Encoding);
                            using (var reader = new StreamReader(section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true))
                            {
                                var value = await reader.ReadToEndAsync();

                                formAccumulator.Append(key, value);
                            }
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false, "Unrecognized content-disposition for this section: " + headers.Get(HeaderNames.ContentDisposition));
                        }

                        section = await multipartReader.ReadNextSectionAsync(cancellationToken);
                    }

                    formFields = formAccumulator.GetResults();
                }
            }

            Form = new FormCollection(formFields, files);
            return(Form);
        }
        public async Task <IActionResult> Upload()
        {
            try
            {
                if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
                {
                    return(BadRequest($"Expected a multipart request, but got {Request.ContentType}"));
                }

                // Used to accumulate all the form url encoded key value pairs in the request.
                var    formAccumulator = new KeyValueAccumulator();
                string targetFilePath  = null;

                var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), DefaultFormOptions.MultipartBoundaryLengthLimit);
                var reader   = new MultipartReader(boundary, HttpContext.Request.Body);

                var section = await reader.ReadNextSectionAsync();

                while (section != null)
                {
                    var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
                    if (hasContentDispositionHeader)
                    {
                        if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                        {
                            targetFilePath = Path.GetTempFileName();
                            using (var targetStream = System.IO.File.Create(targetFilePath))
                            {
                                await section.Body.CopyToAsync(targetStream);

                                _logger.LogInformation($"Copied the uploaded file '{targetFilePath}'");
                            }
                        }
                        else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                        {
                            // Do not limit the key name length here because the
                            // multipart headers length limit is already in effect.
                            var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                            var encoding = GetEncoding(section);
                            using (var streamReader = new StreamReader(section.Body, encoding, true, 1024, true))
                            {
                                // The value length limit is enforced by MultipartBodyLengthLimit
                                var value = await streamReader.ReadToEndAsync();

                                if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                                {
                                    value = string.Empty;
                                }
                                formAccumulator.Append(key.ToString(), value);

                                if (formAccumulator.ValueCount > DefaultFormOptions.ValueCountLimit)
                                {
                                    throw new InvalidDataException($"Form key count limit {DefaultFormOptions.ValueCountLimit} exceeded.");
                                }
                            }
                        }
                    }

                    // Drains any remaining section body that has not been consumed and reads the headers for the next section.
                    section = await reader.ReadNextSectionAsync();
                }

                if (string.IsNullOrEmpty(targetFilePath) || !System.IO.File.Exists(targetFilePath))
                {
                    _logger.LogError("File not created!");
                    return(StatusCode(500, "Internal server error"));
                }

                // Import the file
                Stopwatch sw = new Stopwatch();
                sw.Start();
                await _fileImport.ImportAsync(targetFilePath);

                sw.Stop();
                TimeSpan ts = sw.Elapsed;
                _logger.LogInformation(string.Format("Import run time: {0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10));

                return(Ok(true));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                return(StatusCode(500, "Internal server error"));
            }
        }
Example #8
0
        public async Task <IActionResult> Upload()
        {
            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                return(BadRequest($"Expected a multipart request, got {Request.ContentType}"));
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            string targetFilePath = null;
            string boundary       = MediaTypeHeaderValue.Parse(Request.ContentType).GetBoundary(FormOptions.MultipartBoundaryLengthLimit);
            KeyValueAccumulator formAccumulator = new KeyValueAccumulator();
            MultipartReader     reader          = new MultipartReader(boundary, HttpContext.Request.Body);
            MultipartSection    section         = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                bool hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (contentDisposition.HasFileContentDisposition())
                    {
                        targetFilePath = Path.GetTempFileName();

                        await using (FileStream targetStream = System.IO.File.Create(targetFilePath))
                        {
                            await section.Body.CopyToAsync(targetStream);
                        }
                    }
                    else if (contentDisposition.HasFileContentDisposition())
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        StringSegment key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        Encoding      encoding = GetEncoding(section);

                        using (StreamReader streamReader = new StreamReader(section.Body, encoding, true, Constants.BUFFER_KB, true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            string value = await streamReader.ReadToEndAsync();

                            if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = string.Empty;
                            }
                            formAccumulator.Append(key.Value, value);
                            if (formAccumulator.ValueCount > FormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {FormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            if (string.IsNullOrWhiteSpace(targetFilePath))
            {
                return(BadRequest("File could not be read or content disposition header is invalid."));
            }

            FormValueProvider formValueProvider = new FormValueProvider(BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture);

            return(await FileUploaded(targetFilePath, formValueProvider));
        }
Example #9
0
        public static Dictionary <string, StringValues> ParseNullableQuery(string queryString,
                                                                           string ignoreTrimKey = "sign")
        {
            var accumulator = new KeyValueAccumulator();

            if (string.IsNullOrEmpty(queryString) || queryString == "?")
            {
                return(null);
            }

            var scanIndex = 0;

            if (queryString[0] == '?')
            {
                scanIndex = 1;
            }

            var textLength = queryString.Length;
            var equalIndex = queryString.IndexOf('=');

            if (equalIndex == -1)
            {
                equalIndex = textLength;
            }

            while (scanIndex < textLength)
            {
                var delimiterIndex = queryString.IndexOf('&', scanIndex);
                if (delimiterIndex == -1)
                {
                    delimiterIndex = textLength;
                }

                if (equalIndex < delimiterIndex)
                {
                    while (scanIndex != equalIndex && char.IsWhiteSpace(queryString[scanIndex]))
                    {
                        ++scanIndex;
                    }
                    var name  = queryString.Substring(scanIndex, equalIndex - scanIndex);
                    var value = queryString.Substring(equalIndex + 1, delimiterIndex - equalIndex - 1);
                    if (name == ignoreTrimKey)
                    {
                        accumulator.Append(
                            Uri.UnescapeDataString(name),
                            Uri.UnescapeDataString(value));
                        equalIndex = queryString.IndexOf('=', delimiterIndex);
                    }
                    else
                    {
                        accumulator.Append(
                            Uri.UnescapeDataString(name),
                            Uri.UnescapeDataString(value.Replace('+', ' ')));
                        equalIndex = queryString.IndexOf('=', delimiterIndex);
                    }

                    if (equalIndex == -1)
                    {
                        equalIndex = textLength;
                    }
                }
                else
                {
                    if (delimiterIndex > scanIndex)
                    {
                        accumulator.Append(queryString.Substring(scanIndex, delimiterIndex - scanIndex), string.Empty);
                    }
                }

                scanIndex = delimiterIndex + 1;
            }

            if (!accumulator.HasValues)
            {
                return(null);
            }

            return(accumulator.GetResults());
        }
Example #10
0
 public DeviceFile()
 {
     formAccumulator = new KeyValueAccumulator();
     memoryStream    = new MemoryStream();
 }
Example #11
0
        public async Task <IActionResult> Upload([FromRoute] string uploadName, [FromQuery(Name = "k")] string apiKeyQuery)
        {
            var apiKeys = HttpContext.Request.Headers["ApiKey"];
            var apiKey  = apiKeys.Count == 1 ? apiKeys[0] : apiKeyQuery;

            var uploader =
                _options.Uploader.FirstOrDefault(
                    s => s.WebBasePath.Equals(uploadName, StringComparison.OrdinalIgnoreCase) &&
                    (s.ApiKey.Equals(apiKey) || string.IsNullOrEmpty(s.ApiKey)));

            if (uploader == null)
            {
                return(BadRequest("Uploader not found, invalid upload path or invalid API key."));
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var    formAccumulator = new KeyValueAccumulator();
            string targetFilePath  = null;

            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(Request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            string fileExtension = null;

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);


                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        fileExtension  = Path.GetExtension(contentDisposition.FileName.Value).ToLower();
                        targetFilePath = Path.GetTempFileName();
                        if (!uploader.FileExtensions.Contains(fileExtension) && !uploader.FileExtensions.Contains("*"))
                        {
                            return(BadRequest(
                                       $"File does not meet the requirements. Invalid extension ({fileExtension}), allowed extensions: [{string.Join(", ", uploader.FileExtensions)}]"));
                        }
                        try
                        {
                            using (var targetStream = System.IO.File.Create(targetFilePath))
                            {
                                await section.Body.CopyToAsync(targetStream);

                                _logger.LogInformation($"Copied the uploaded file '{targetFilePath}'");
                            }
                        }
                        catch (Exception)
                        {
                            _logger.LogError("An error occured while streaming the File. Did the client cancel?");
                            DeleteFileIfExists(targetFilePath);
                        }
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);

                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = string.Empty;
                            }
                            formAccumulator.Append(key.Value, value);

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            // Bind form data to a model
            var model             = new PostFileModel();
            var formValueProvider = new FormValueProvider(
                BindingSource.Form,
                new FormCollection(formAccumulator.GetResults()),
                CultureInfo.CurrentCulture);

            var bindingSuccessful = await TryUpdateModelAsync(model, prefix : "",
                                                              valueProvider : formValueProvider);

            if (!bindingSuccessful && !ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }


            var file = new FileInfo(targetFilePath ?? throw new InvalidOperationException());

            if (!ValidateFileSize(uploader.MaxFileSize, file.Length))
            {
                file.Delete();
                return(BadRequest($"File does not meet the Requirements. Maximum size {uploader.MaxFileSize}MB."));
            }

            Directory.CreateDirectory(uploader.LocalBasePath);
            var fileName = GetRandomFileName(fileExtension);
            var filePath = Path.Combine(uploader.LocalBasePath, fileName);
            var fileSize = file.Length;

            if (uploader.MaxFolderSize > 0)
            {
                if (fileSize > uploader.MaxFolderSize * 1024 * 1024)
                {
                    file.Delete();
                    return(BadRequest("File bigger than max foldersize"));
                }

                while (GetDirectorySize(uploader.LocalBasePath) + fileSize > uploader.MaxFolderSize * 1024 * 1024)
                {
                    DeleteOldestFile(uploader.LocalBasePath);
                }
            }

            while (System.IO.File.Exists(filePath))
            {
                fileName = GetRandomFileName(fileExtension);
                filePath = Path.Combine(uploader.LocalBasePath, fileName);
            }

            file.MoveTo(filePath);


            if (uploader.ResponseType == ApiResponseType.Redirect)
            {
                return(LocalRedirect($"/{uploader.WebBasePath}/{fileName}"));
            }

            return(Ok(new ResultModel
            {
                FileUrl = ToAbsoluteUrl(Url.Content(uploader.WebBasePath + "/" + fileName)),
                DeleteUrl = ToAbsoluteUrl(Url.Action("Delete", "Uploader",
                                                     new { uploadName = uploader.WebBasePath, fileName }))
            }));
        }
Example #12
0
        //[ValidateAntiForgeryToken]
        public async Task <IActionResult> Upload()
        {
            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                return(BadRequest($"Expected a multipart request, but got {Request.ContentType}"));
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var formAccumulator = new KeyValueAccumulator();

            var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), DefaultFormOptions.MultipartBoundaryLengthLimit);
            var reader   = new MultipartReader(boundary, HttpContext.Request.Body);

            var links = new List <string>();

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        var url = await _imageUploadService.UploadImage(contentDisposition.FileName.Value, section.Body);

                        links.Add(url);
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = string.Empty;
                            }
                            formAccumulator.Append(key.Value, value);

                            if (formAccumulator.ValueCount > DefaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {DefaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            return(Ok(links));
        }
Example #13
0
        public async Task <ResultEntityBase> UploadVideo(CancellationToken cancellationToken)
        {
            var result = new ResultEntityBase();
            var video  = new Video();

            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                result.Status  = CommonEntity.StatusCode.Error;
                result.Message = "请求数据类型出错";
                return(await Task.FromResult(result));
            }
            var formAccumulator = new KeyValueAccumulator();

            string videoUid = Guid.NewGuid().ToString("N");

            video.Uid   = videoUid;
            video.State = 1;
            string targetFilePath = Path.Combine(Directory.GetCurrentDirectory(), $"{_iconfiguration.GetValue<string>("VirtualPath")}/{videoUid}");

            //检查相应目录
            if (!Directory.Exists(targetFilePath))
            {
                Directory.CreateDirectory(targetFilePath);
            }
            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(Request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, HttpContext.Request.Body);

            try
            {
                var section = await reader.ReadNextSectionAsync();

                while (section != null)
                {
                    ContentDispositionHeaderValue contentDisposition;
                    var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

                    if (hasContentDispositionHeader)
                    {
                        if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                        {
                            var fileName = section.AsFileSection().FileName;
                            video.FileName   = fileName;
                            video.Name       = fileName;
                            video.UpdateUser = "******";
                            video.CreateUser = "******";
                            targetFilePath   = Path.Combine(targetFilePath, fileName);
                            if (System.IO.File.Exists(targetFilePath))
                            {
                                result.Status  = CommonEntity.StatusCode.Error;
                                result.Message = "文件已存在";
                                break;
                            }
                            using (var targetStream = System.IO.File.Create(targetFilePath))
                            {
                                await section.Body.CopyToAsync(targetStream);

                                _ilogger.LogInformation($"复制文件到该路径下 '{targetFilePath}'");
                            }
                        }
                        else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                        {
                            // Content-Disposition: form-data; name="key"
                            //
                            // value

                            // Do not limit the key name length here because the
                            // multipart headers length limit is already in effect.
                            var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                            var encoding = GetEncoding(section);
                            using (var streamReader = new StreamReader(
                                       section.Body,
                                       encoding,
                                       detectEncodingFromByteOrderMarks: true,
                                       bufferSize: 1024,
                                       leaveOpen: true))
                            {
                                // The value length limit is enforced by MultipartBodyLengthLimit
                                var value = await streamReader.ReadToEndAsync();

                                if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                                {
                                    value = String.Empty;
                                }
                                formAccumulator.Append(key.ToString(), value);

                                if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                                {
                                    throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                                }
                            }
                        }
                    }
                    // Drains any remaining section body that has not been consumed and
                    // reads the headers for the next section.
                    section = await reader.ReadNextSectionAsync();
                }
                video.Name      = formAccumulator.GetResults()["name"];
                video.Title     = formAccumulator.GetResults()["title"];
                video.SecertKey = videoUid;
                video.State     = Convert.ToInt32(formAccumulator.GetResults()["state"]);
                return(await Task.FromResult(await _ivideoService.InsertVideoAsync(video)));
            }
            catch (OperationCanceledException)
            {
                if (System.IO.File.Exists(targetFilePath))
                {
                    System.IO.File.Delete(targetFilePath);
                }
                result.Status  = CommonEntity.StatusCode.Error;
                result.Message = "用户取消上传操作";
                return(await Task.FromResult(result));
            }
            catch (Exception ex)
            {
                if (System.IO.File.Exists(targetFilePath))
                {
                    System.IO.File.Delete(targetFilePath);
                }
                result.Status  = CommonEntity.StatusCode.Error;
                result.Message = "取消上传操作";
                _ilogger.LogError(new EventId(), ex, ex.Message);
                return(await Task.FromResult(result));
            }
        }
Example #14
0
        public static async Task <(FormValueProvider fvp, List <BasicImage> bi)> StreamFile(this HttpRequest request)
        {
            if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType))
            {
                throw new Exception($"Expected a multipart request, but got {request.ContentType}");
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var formAccumulator = new KeyValueAccumulator();
            int positionCounter = 1;

            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, request.Body);
            List <BasicImage> images = new List <BasicImage>();

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        string fileext = System.IO.Path.GetExtension(contentDisposition.FileName.ToString());
                        string guid    = Guid.NewGuid().ToString();
                        string pathUID = guid + fileext;
                        using (var stream = System.IO.File.Create("c:\\temp\\" + pathUID))
                        {
                            await section.Body.CopyToAsync(stream);

                            BasicImage bi = new BasicImage
                            {
                                //Initialise as -1 prior to autogeneration of PropertyID image is bound to
                                PropertyRef = -1,
                                Position    = positionCounter++,
                                Path        = pathUID
                            };
                            images.Add(bi);
                        }
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new System.IO.StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key.Value, value); // For .NET Core <2.0 remove ".Value" from key

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new System.IO.InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            // Bind form data to a model
            var formValueProvider = new FormValueProvider(
                BindingSource.Form,
                new FormCollection(formAccumulator.GetResults()),
                CultureInfo.CurrentCulture);

            return(formValueProvider, images);
        }
        protected async Task <KeyValueAccumulator> BuildMultiPartFormAccumulator <TModel>() where TModel : class, new()
        {
            var httpContextRequest = HttpContext.Request;

            // Used to accumulate all the form url encoded key value pairs in the request
            var formAccumulator = new KeyValueAccumulator();

            var boundary = Request.GetBoundary(_defaultFormOptions);
            var reader   = new MultipartReader(boundary, httpContextRequest.Body);

            Logger.LogDebug("Reading next section");

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader =
                    ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader)
                {
                    Logger.LogDebug("Content Disposition Header: {0}", section.ContentDisposition);

                    if (contentDisposition.IsFileContentDisposition())
                    {
                        var fileName = contentDisposition.FileName.Value;

                        var formFileNames = FormFileAttributeHelper.GetFormFileNames(typeof(TModel));
                        if (!formFileNames.Contains(contentDisposition.Name.Value))
                        {
                            Logger.LogWarning($"Unknown file '{contentDisposition.Name.Value}' with fileName: '{fileName}' is being ignored.");
                            // Drains any remaining section body that has not been consumed and
                            // reads the headers for the next section.
                            section = await reader.ReadNextSectionAsync();

                            continue;
                        }

                        formAccumulator.Append(contentDisposition.Name.Value, fileName);

                        var path = await TempFileService.CreateFromStreamAsync(fileName, section.Body);

                        Logger.LogInformation($"Copied the uploaded file '{fileName}' to path: '{path}'");
                    }
                    else if (contentDisposition.IsFormDataContentDisposition())
                    {
                        // Content-Disposition: form-data; name="key"

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name);

                        Logger.LogDebug("Retrieving value for {0}", key);

                        var encoding     = section.GetEncoding();
                        var streamReader = new StreamReader(
                            section.Body,
                            encoding,
                            detectEncodingFromByteOrderMarks: true,
                            bufferSize: 1024,
                            leaveOpen: true);
                        using (streamReader)
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = string.Empty;
                            }

                            formAccumulator.Append(key.Value, value);

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException(
                                          $"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            return(formAccumulator);
        }
Example #16
0
        public async Task <IActionResult> Post()
        {
            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                return(BadRequest($"Expected a multipart request, but got {Request.ContentType}"));
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var    formAccumulator       = new KeyValueAccumulator();
            string targetFilePath        = null;
            string targetFileContentType = null;
            var    boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(Request.ContentType),
                DefaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        targetFilePath        = Path.GetTempFileName();
                        targetFileContentType = section.ContentType;
                        var fileName = GetFileName(section.ContentDisposition);
                        using (var targetStream = new FileStream(fileName, FileMode.Append))
                        {
                            await _storage.StoreAndGetFile(fileName, "talentcontest", targetFileContentType, targetStream);

                            //await section.Body.CopyToAsync(targetStream);

                            _logger.LogInformation($"Copied the uploaded file '{targetFilePath}'");
                        }
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key.ToString(), value);

                            if (formAccumulator.ValueCount > DefaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {DefaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            // Bind form data to a model
            var entry             = new SubmissionViewModel();
            var formValueProvider = new FormValueProvider(
                BindingSource.Form,
                new FormCollection(formAccumulator.GetResults()),
                CultureInfo.CurrentCulture);

            var bindingSuccessful = await TryUpdateModelAsync(entry, prefix : "",
                                                              valueProvider : formValueProvider);

            if (!bindingSuccessful)
            {
                if (!ModelState.IsValid)
                {
                    return(BadRequest(ModelState));
                }
            }

            var uploadedData = new Submission
            {
                FirstName      = entry.FirstName,
                LastName       = entry.LastName,
                Email          = entry.Email,
                ManagerName    = entry.ManagerName,
                LocationId     = entry.LocationId,
                PhoneNumber    = entry.PhoneNumber,
                FileName       = entry.FileName,
                Talent         = entry.Talent,
                ImageConsent   = entry.ImageConsent,
                ContestConsent = entry.ContestConsent,
                EmployeeId     = entry.EmployeeId
            };

            return(Json(uploadedData));
        }
Example #17
0
        public async Task <IActionResult> Upload()
        {
            //StringValues UniqueUploadId = default(StringValues);
            //StringValues UploadType = default(StringValues);

            //Request.Headers.TryGetValue("unique-upload-id", out UniqueUploadId);
            //Request.Headers.TryGetValue("upload-type", out UploadType);
            Request.Headers.TryGetValue("X-Upload-Title", out StringValues uploadTitle);
            Request.Headers.TryGetValue("X-Date-Taken", out StringValues dateTaken);

            var user = await _userManager.GetUserAsync(User);

            if (user == null)
            {
                return(BadRequest());
            }

            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                return(BadRequest($"Expected a multipart request, but got {Request.ContentType}"));
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var formAccumulator = new KeyValueAccumulator();

            var         objectKey      = Guid.NewGuid().ToString();
            var         thumbObjectKey = $"{Guid.NewGuid()}.jpg";
            FileStorage parent         = null;

            var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), DefaultFormOptions.MultipartBoundaryLengthLimit);
            var reader   = new MultipartReader(boundary, HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        var targetFilePath = Path.GetTempFileName();
                        using (var targetStream = System.IO.File.Create(targetFilePath)) {
                            await section.Body.CopyToAsync(targetStream);

                            _logger.LogInformation($"Copied the uploaded file '{targetFilePath}'");
                        }

                        var partName         = contentDisposition.Name;
                        var strippedFileName = contentDisposition.FileName.Replace("\"", string.Empty);
                        var mimeType         = MimeTypesHelper.GetMimeType(strippedFileName);
                        var fileExtension    = $".{strippedFileName.Split('.').LastOrDefault()}";
                        var originalFileName = strippedFileName.Replace(fileExtension, string.Empty);

                        var type   = FileStorageType.Thumb;
                        var isFile = partName.Replace("\"", string.Empty) == "file";

                        if (mimeType.Contains("image") && isFile)
                        {
                            type = FileStorageType.Image;
                        }
                        else if (mimeType.Contains("video") && isFile)
                        {
                            type = FileStorageType.Video;
                        }

                        if (isFile)
                        {
                            objectKey = $"{objectKey}{fileExtension}";
                        }

                        try {
                            using (var amazonClient = new AmazonS3Helper(_amazonS3, "attorney-journal-dev")) {
                                await amazonClient.UploadFileAsync(targetFilePath, isFile?objectKey : thumbObjectKey);
                            }

                            var date = new DateTime();
                            try {
                                date = DateTime.Parse(dateTaken);
                            } catch (System.Exception) { }

                            var newFile = new FileStorage {
                                Parent          = parent,
                                AmazonObjectKey = isFile ? objectKey : thumbObjectKey,
                                CreatedAt       = DateTime.UtcNow,
                                FileExtension   = fileExtension,
                                OriginalName    = originalFileName,
                                MimeType        = mimeType,
                                Owner           = user,
                                Type            = type,
                                Title           = uploadTitle.FirstOrDefault() ?? string.Empty,
                                DateTaken       = date
                            };

                            _context.Files.Add(newFile);

                            parent = isFile ? newFile : null;
                        } catch (AmazonS3Exception s3Exception) {
                            Console.WriteLine(s3Exception.Message, s3Exception.InnerException);
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            // Bind form data to a model
            var formValueProvider = new FormValueProvider(BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture);

            var bindingSuccessful = await TryUpdateModelAsync(new { }, string.Empty, formValueProvider);

            if (!bindingSuccessful || !ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            await _context.SaveChangesAsync(CancellationToken.None);

            return(Json(new { fileUrl = AmazonS3Helper.GenerateUrl(objectKey), thumbUrl = AmazonS3Helper.GenerateUrl(thumbObjectKey), result = true }));
        }
Example #18
0
        public async Task <ActionResult <UploadResult> > Upload()
        {
            var multipartBoundary = Request.GetMultipartBoundary();

            if (string.IsNullOrEmpty(multipartBoundary))
            {
                return(BadRequest($"Expected a multipart request, but got '{Request.ContentType}'."));
            }

            var formAccumulator = new KeyValueAccumulator();
            var reader          = new MultipartReader(multipartBoundary, HttpContext.Request.Body);
            var section         = await reader.ReadNextSectionAsync();

            var fileGuid      = Guid.NewGuid();
            var userId        = _userManager.GetUserId(HttpContext.User);
            var fileExtension = string.Empty;

            while (section != null)
            {
                var fileSection = section.AsFileSection();

                if (fileSection != null)
                {
                    var fileName = fileSection.FileName;
                    fileExtension = Path.GetExtension(fileName);
                    var targetFolderPath = Path.Combine(_hostingEnvironment.WebRootPath, _appSettings.UploadsFolder, userId);
                    var targetFilePath   = Path.Combine(_hostingEnvironment.WebRootPath, _appSettings.UploadsFolder, userId, $"{fileGuid}{fileExtension}");

                    if (!Directory.Exists(targetFolderPath))
                    {
                        Directory.CreateDirectory(targetFolderPath);
                    }

                    using (var targetStream = System.IO.File.Create(targetFilePath)) {
                        await fileSection.FileStream.CopyToAsync(targetStream);

                        _logger.LogInformation($"Copied the uploaded file '{fileName}' to '{targetFilePath}'.");
                    }
                }
                else
                {
                    var formSection = section.AsFormDataSection();

                    if (formSection != null)
                    {
                        var name  = formSection.Name;
                        var value = await formSection.GetValueAsync();

                        formAccumulator.Append(name, value);

                        if (formAccumulator.ValueCount > FormReader.DefaultValueCountLimit)
                        {
                            throw new InvalidDataException($"Form key count limit {FormReader.DefaultValueCountLimit} exceeded.");
                        }
                    }
                }

                section = await reader.ReadNextSectionAsync();
            }

            return(Ok(new UploadResult {
                Succeeded = true,
                Description = "File was uploaded successfully",
                FileUrl = $"{_appSettings.Domain}/{_appSettings.UploadsFolder}/{userId}/{fileGuid}{fileExtension}",
                FileName = $"{fileGuid}{fileExtension}"
            }));
        }
Example #19
0
        public async Task <IActionResult> PostAppFileStream()
        {
            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                ModelState.AddModelError("File",
                                         $"The request couldn't be processed (Error 1).");
                // Log error

                return(BadRequest(ModelState));
            }

            // Accumulate the form data key-value pairs in the request (formAccumulator).
            var formAccumulator             = new KeyValueAccumulator();
            var trustedFileNameForDisplay   = string.Empty;
            var untrustedFileNameForStorage = string.Empty;
            var streamedFileContent         = new byte[0];

            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(Request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                var hasContentDispositionHeader =
                    ContentDispositionHeaderValue.TryParse(
                        section.ContentDisposition, out var contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper
                        .HasFileContentDisposition(contentDisposition))
                    {
                        untrustedFileNameForStorage = contentDisposition.FileName.Value;
                        // Don't trust the file name sent by the client. To display
                        // the file name, HTML-encode the value.
                        trustedFileNameForDisplay = WebUtility.HtmlEncode(
                            contentDisposition.FileName.Value);

                        streamedFileContent =
                            await FileHelpers.ProcessStreamedFile(section, contentDisposition,
                                                                  ModelState, _permittedExtensions, _fileSizeLimit);

                        if (!ModelState.IsValid)
                        {
                            return(BadRequest(ModelState));
                        }
                    }
                    else if (MultipartRequestHelper
                             .HasFormDataContentDisposition(contentDisposition))
                    {
                        // Don't limit the key name length because the
                        // multipart headers length limit is already in effect.
                        var key = HeaderUtilities
                                  .RemoveQuotes(contentDisposition.Name).Value;
                        var encoding = GetEncoding(section);

                        if (encoding == null)
                        {
                            ModelState.AddModelError("File",
                                                     $"The request couldn't be processed (Error 2).");
                            // Log error

                            return(BadRequest(ModelState));
                        }

                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by
                            // MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (string.Equals(value, "undefined",
                                              StringComparison.OrdinalIgnoreCase))
                            {
                                value = string.Empty;
                            }

                            formAccumulator.Append(key, value);

                            if (formAccumulator.ValueCount >
                                _defaultFormOptions.ValueCountLimit)
                            {
                                // Form key count limit of
                                // _defaultFormOptions.ValueCountLimit
                                // is exceeded.
                                ModelState.AddModelError("File",
                                                         $"The request couldn't be processed (Error 3).");
                                // Log error

                                return(BadRequest(ModelState));
                            }
                        }
                    }
                }

                // Drain any remaining section body that hasn't been consumed and
                // read the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            // Bind form data to the model
            var formData          = new FormData();
            var formValueProvider = new FormValueProvider(
                BindingSource.Form,
                new FormCollection(formAccumulator.GetResults()),
                CultureInfo.CurrentCulture);
            var bindingSuccessful = await TryUpdateModelAsync(formData, prefix : "",
                                                              valueProvider : formValueProvider);

            if (!bindingSuccessful)
            {
                ModelState.AddModelError("File",
                                         "The request couldn't be processed (Error 5).");
                // Log error

                return(BadRequest(ModelState));
            }

            // **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 app.

            var file = new AppFile()
            {
                Content       = streamedFileContent,
                UntrustedName = untrustedFileNameForStorage,
                Note          = formData.Note,
                Size          = streamedFileContent.Length,
                UploadDT      = DateTime.UtcNow
            };

            _context.File.Add(file);
            await _context.SaveChangesAsync();

            return(Created($"api/AppFiles/{file.Id}", null));
        }
Example #20
0
        /// <summary>
        /// 以流的形式保存文件
        /// </summary>
        /// <param name="request"></param>
        /// <param name="targetDirectory">e:\ws\music\files</param>
        /// <returns></returns>
        public static async Task <FormValueProvider> StreamFiles(this HttpRequest request, string targetDirectory)
        {
            if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType))
            {
                throw new Exception($"Expected a multipart request, but got {request.ContentType}");
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var formAccumulator = new KeyValueAccumulator();

            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, request.Body);

            var section = await reader.ReadNextSectionAsync();//用于读取Http请求中的第一个section数据

            while (section != null)
            {
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

                if (hasContentDispositionHeader)
                {
                    /*
                     * 用于处理上传文件类型的的section
                     * -----------------------------99614912995
                     * Content - Disposition: form - data; name = "files"; filename = "Misc 002.jpg"
                     *
                     * ASAADSDSDJXCKDSDSDSHAUSAUASAASSDSDFDSFJHSIHFSDUIASUI+/==
                     * -----------------------------99614912995
                     */
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        var fileName     = MultipartRequestHelper.GetFileName(contentDisposition);
                        var fileGuid     = Guid.NewGuid().ToString();
                        var fileExt      = System.IO.Path.GetExtension(fileName);
                        var destFileName = fileGuid + fileExt;
                        var relDir       = "";
                        switch (section.ContentType.Split("/")[0])
                        {
                        case "video":
                            relDir += "\\Video";
                            break;

                        case "audio":
                            relDir += "\\Audio";
                            break;

                        case "image":
                            relDir += "\\Image";
                            break;

                        case "text":
                            relDir += "\\Text";
                            break;

                        default:
                            relDir += "\\Other";
                            break;
                        }
                        var relPath = relDir + "\\" + destFileName;
                        var path    = targetDirectory + relDir + "\\" + destFileName;
                        var dir     = System.IO.Path.GetDirectoryName(path);
                        if (!System.IO.Directory.Exists(dir))
                        {
                            System.IO.Directory.CreateDirectory(dir);
                        }
                        var now = DateTime.Now;
                        // 文件保存成功后保存文件信息到数据库
                        var fileInfo = new FileInfo
                        {
                            FileGuid    = fileGuid,
                            Path        = path,
                            Url         = "/file" + relDir.Replace("\\", "/").ToLower() + "/" + destFileName, // /Files/Images/guid.ext | /Files/Audios/guid.ext
                            RelPath     = relPath,
                            SrcPath     = fileName,
                            ContentType = section.ContentType,
                            FileExt     = fileExt,
                            Length      = section.Body.Length,
                            CreateTime  = now,
                            UpdateTime  = now,
                            VisitTime   = now
                        };
                        Console.WriteLine("[FileStreamingHelper] [StreamFiles] FileInfo: " + Newtonsoft.Json.JsonConvert.SerializeObject(fileInfo));
                        formAccumulator.Append("fileInfo", Newtonsoft.Json.JsonConvert.SerializeObject(fileInfo));

                        var loadBufferBytes = 1024;//这个是每一次从Http请求的section中读出文件数据的大小,单位是Byte即字节,这里设置为1024的意思是,每次从Http请求的section数据流中读取出1024字节的数据到服务器内存中,然后写入下面targetFileStream的文件流中,可以根据服务器的内存大小调整这个值。这样就避免了一次加载所有上传文件的数据到服务器内存中,导致服务器崩溃。
                        using (var targetFileStream = System.IO.File.Create(path))
                        {
                            //section.Body是System.IO.Stream类型,表示的是Http请求中一个section的数据流,从该数据流中可以读出每一个section的全部数据,所以我们下面也可以不用section.Body.CopyToAsync方法,而是在一个循环中用section.Body.Read方法自己读出数据,再将数据写入到targetFileStream
                            // 注意一个section是否是一个文件的片段
                            await section.Body.CopyToAsync(targetFileStream, loadBufferBytes);
                        }
                    }

                    /*
                     * 用于处理表单键值数据的section
                     * -----------------------------99614912995
                     * Content - Disposition: form - data; name = "SOMENAME"
                     *
                     * Formulaire de Quota
                     * -----------------------------99614912995
                     */
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new System.IO.StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key.Value, value); // For .NET Core <2.0 remove ".Value" from key

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new System.IO.InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();//用于读取Http请求中的下一个section数据
            }

            // Bind form data to a model
            var formValueProvider = new FormValueProvider(
                BindingSource.Form,
                new FormCollection(formAccumulator.GetResults()),
                CultureInfo.CurrentCulture);

            return(formValueProvider);
        }
Example #21
0
        public static async Task <FormValueProvider> StreamFiles(this HttpRequest request, string targetDirectory)
        {
            if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType))
            {
                throw new Exception($"Expected a multipart request, but got {request.ContentType}");
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var formAccumulator = new KeyValueAccumulator();

            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, request.Body);

            var section = await reader.ReadNextSectionAsync();//用于读取Http请求中的第一个section数据

            while (section != null)
            {
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

                if (hasContentDispositionHeader)
                {
                    /*
                     * 用于处理上传文件类型的的section
                     * -----------------------------99614912995
                     * Content - Disposition: form - data; name = "files"; filename = "Misc 002.jpg"
                     *
                     * ASAADSDSDJXCKDSDSDSHAUSAUASAASSDSDFDSFJHSIHFSDUIASUI+/==
                     * -----------------------------99614912995
                     */
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        if (!Directory.Exists(targetDirectory))
                        {
                            Directory.CreateDirectory(targetDirectory);
                        }

                        var fileName = MultipartRequestHelper.GetFileName(contentDisposition);

                        var loadBufferBytes = 1024;//这个是每一次从Http请求的section中读出文件数据的大小,单位是Byte即字节,这里设置为1024的意思是,每次从Http请求的section数据流中读取出1024字节的数据到服务器内存中,然后写入下面targetFileStream的文件流中,可以根据服务器的内存大小调整这个值。这样就避免了一次加载所有上传文件的数据到服务器内存中,导致服务器崩溃。

                        using (var targetFileStream = System.IO.File.Create(targetDirectory + "\\" + fileName))
                        {
                            using (section.Body)
                            {
                                //section.Body是System.IO.Stream类型,表示的是Http请求中一个section的数据流,从该数据流中可以读出每一个section的全部数据,所以我们下面也可以不用section.Body.CopyToAsync方法,而是在一个循环中用section.Body.Read方法自己读出数据(如果section.Body.Read方法返回0,表示数据流已经到末尾,数据已经全部都读取完了),再将数据写入到targetFileStream
                                await section.Body.CopyToAsync(targetFileStream, loadBufferBytes);
                            }
                        }
                    }

                    /*
                     * 用于处理表单键值数据的section
                     * -----------------------------99614912995
                     * Content - Disposition: form - data; name = "SOMENAME"
                     *
                     * Formulaire de Quota
                     * -----------------------------99614912995
                     */
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key.Value, value); // For .NET Core <2.0 remove ".Value" from key

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();//用于读取Http请求中的下一个section数据
            }

            // Bind form data to a model
            var formValueProvider = new FormValueProvider(
                BindingSource.Form,
                new FormCollection(formAccumulator.GetResults()),
                CultureInfo.CurrentCulture);

            return(formValueProvider);
        }
Example #22
0
        public async Task <IActionResult> PostImage(string nihii)
        {
            try
            {
                if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
                {
                    return(BadRequest($"Expected a multipart request, but got {Request.ContentType}"));
                }

                // Used to accumulate all the form url encoded key value pairs in the
                // request.
                var formAccumulator = new KeyValueAccumulator();
                var boundary        = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), 52000);
                var reader          = new MultipartReader(boundary, HttpContext.Request.Body);
                var section         = await reader.ReadNextSectionAsync();

                while (section != null)
                {
                    ContentDispositionHeaderValue contentDisposition;
                    var hasContentDispositionHeader =
                        ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

                    if (hasContentDispositionHeader)
                    {
                        if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                        {
                            using (var targetStream = new MemoryStream())
                            {
                                await section.Body.CopyToAsync(targetStream);

                                var  imageName = contentDisposition.FileName.ToString();
                                bool isImage   = false;
                                foreach (var ext in imageExtensions)
                                {
                                    if (imageName.ToLower().EndsWith(ext))
                                    {
                                        isImage = true;
                                    }
                                }

                                imageName = $"{nihii}/" + imageName;
                                //imageName = isImage ? $"{nihii}/images/" + imageName : $"{nihii}/documents/" + imageName;

                                var photoUriResponse = await _storageService.Post(imageName, targetStream.ToArray());

                                if (!photoUriResponse.Success)
                                {
                                    return(BadRequest(photoUriResponse.Error));
                                }
                                return(Json($"{imageName}.jpg"));
                            }
                        }
                        else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                        {
                            var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                            using (var streamReader = new StreamReader(section.Body, Encoding.UTF8, true, 1024, true))
                            {
                                var value = await streamReader.ReadToEndAsync();

                                if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                                {
                                    value = string.Empty;
                                }
                                formAccumulator.Append(key.Value, value);
                            }
                        }
                    }
                    section = await reader.ReadNextSectionAsync();
                }

                return(NoContent());
            }
            catch (Exception ex)
            {
                return(BadRequest(ex.Message + " ---" + ex.StackTrace));
            }
        }
Example #23
0
        private async Task <IFormCollection> InnerReadFormAsync(CancellationToken cancellationToken)
        {
            if (!HasFormContentType)
            {
                throw new InvalidOperationException("Incorrect Content-Type: " + _request.ContentType);
            }

            cancellationToken.ThrowIfCancellationRequested();

            if (_request.ContentLength == 0)
            {
                return(FormCollection.Empty);
            }

            if (_options.BufferBody)
            {
                _request.EnableRewind(_options.MemoryBufferThreshold, _options.BufferBodyLengthLimit);
            }

            FormCollection     formFields = null;
            FormFileCollection files      = null;

            // Some of these code paths use StreamReader which does not support cancellation tokens.
            using (cancellationToken.Register((state) => ((HttpContext)state).Abort(), _request.HttpContext))
            {
                var contentType = ContentType;
                // Check the content-type
                if (HasApplicationFormContentType(contentType))
                {
                    var encoding = FilterEncoding(contentType.Encoding);
                    using (var formReader = new FormReader(_request.Body, encoding)
                    {
                        ValueCountLimit = _options.ValueCountLimit,
                        KeyLengthLimit = _options.KeyLengthLimit,
                        ValueLengthLimit = _options.ValueLengthLimit,
                    })
                    {
                        formFields = new FormCollection(await formReader.ReadFormAsync(cancellationToken));
                    }
                }
                else if (HasMultipartFormContentType(contentType))
                {
                    var formAccumulator = new KeyValueAccumulator();

                    var boundary        = GetBoundary(contentType, _options.MultipartBoundaryLengthLimit);
                    var multipartReader = new MultipartReader(boundary, _request.Body)
                    {
                        HeadersCountLimit  = _options.MultipartHeadersCountLimit,
                        HeadersLengthLimit = _options.MultipartHeadersLengthLimit,
                        BodyLengthLimit    = _options.MultipartBodyLengthLimit,
                    };
                    var section = await multipartReader.ReadNextSectionAsync(cancellationToken);

                    while (section != null)
                    {
                        // Parse the content disposition here and pass it further to avoid reparsings
                        if (!ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition))
                        {
                            throw new InvalidDataException("Form section has invalid Content-Disposition value: " + section.ContentDisposition);
                        }

                        if (contentDisposition.IsFileDisposition())
                        {
                            var fileSection = new FileMultipartSection(section, contentDisposition);

                            // Enable buffering for the file if not already done for the full body
                            section.EnableRewind(
                                _request.HttpContext.Response.RegisterForDispose,
                                _options.MemoryBufferThreshold, _options.MultipartBodyLengthLimit);

                            // Find the end
                            await section.Body.DrainAsync(cancellationToken);

                            var name     = fileSection.Name;
                            var fileName = fileSection.FileName;

                            FormFile file;
                            if (section.BaseStreamOffset.HasValue)
                            {
                                // Relative reference to buffered request body
                                file = new FormFile(_request.Body, section.BaseStreamOffset.GetValueOrDefault(), section.Body.Length, name, fileName);
                            }
                            else
                            {
                                // Individually buffered file body
                                file = new FormFile(section.Body, 0, section.Body.Length, name, fileName);
                            }
                            file.Headers = new HeaderDictionary(section.Headers);

                            if (files == null)
                            {
                                files = new FormFileCollection();
                            }
                            if (files.Count >= _options.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form value count limit {_options.ValueCountLimit} exceeded.");
                            }
                            files.Add(file);
                        }
                        else if (contentDisposition.IsFormDisposition())
                        {
                            var formDataSection = new FormMultipartSection(section, contentDisposition);

                            // Content-Disposition: form-data; name="key"
                            //
                            // value

                            // Do not limit the key name length here because the multipart headers length limit is already in effect.
                            var key   = formDataSection.Name;
                            var value = await formDataSection.GetValueAsync();

                            formAccumulator.Append(key, value);
                            if (formAccumulator.ValueCount > _options.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form value count limit {_options.ValueCountLimit} exceeded.");
                            }
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false, "Unrecognized content-disposition for this section: " + section.ContentDisposition);
                        }

                        section = await multipartReader.ReadNextSectionAsync(cancellationToken);
                    }

                    if (formAccumulator.HasValues)
                    {
                        formFields = new FormCollection(formAccumulator.GetResults(), files);
                    }
                }
            }

            // Rewind so later readers don't have to.
            if (_request.Body.CanSeek)
            {
                _request.Body.Seek(0, SeekOrigin.Begin);
            }

            if (formFields != null)
            {
                Form = formFields;
            }
            else if (files != null)
            {
                Form = new FormCollection(null, files);
            }
            else
            {
                Form = FormCollection.Empty;
            }

            return(Form);
        }
Example #24
0
        /// <summary>
        /// 这个特性能让这个页面带上验证信息,令牌
        ///
        /// </summary>
        /// <returns></returns>
        //[HttpGet]
        //[GenerateAntiforgeryTokenCookieForAjax]
        //public IActionResult Index()
        //{
        //    return View();
        //}



        #region --上传方法, 不自动绑定,可上传大文件--
        /// <summary>
        /// 上传方法
        /// </summary>
        /// <returns></returns>
        // 1. Disable the form value model binding here to take control of handling
        //    potentially large files.
        //    禁止了表单到模型自动绑定,以便能控制好大文件
        // 2. Typically antiforgery tokens are sent in request body, but since we
        //    do not want to read the request body early, the tokens are made to be
        //    sent via headers. The antiforgery token filter first looks for tokens
        //    in the request header and then falls back to reading the body.
        //[HttpPost]
        //[DisableFormValueModelBinding]//不进行表单到模型的绑定
        //[ValidateAntiForgeryToken]//检查令牌
        protected async Task <IActionResult> Upload(Func <IDictionary <string, StringValues>, string> filePathFunc)
        {
            // 检查是否多部分数据类型
            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                return(BadRequest($"Expected a multipart request, but got {Request.ContentType}"));
            }

            // Used to accumulate all the form url encoded key value pairs in the request.
            var    formAccumulator = new KeyValueAccumulator();
            string targetFilePath  = null; //目标文件路经
            //这里应该是获取http提交的分段信息
            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(Request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            // 创建一个读取器
            var reader = new MultipartReader(boundary, HttpContext.Request.Body);
            // 异步读取下一个部件
            var section = await reader.ReadNextSectionAsync();

            // 循环检查读取的部件是否为空
            while (section != null)
            {
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
                // 是否有内容配置头值
                if (hasContentDispositionHeader)
                {
                    // 是否文件内容配置
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        // 一个临时文件名
                        section.Headers.Keys.Foreach(key => {
                            LogInfo($"{key}:{section.Headers[key]}");
                        });
                        var file_ex = section.ContentDisposition.LastIndexOfRight(".").RemoveFileNameIllegalChar();
                        targetFilePath = Constant.CurrDir + "temp" + DateTime.Now.DataStr("") + "." + file_ex;//Path.GetTempFileName();
                        targetFilePath = filePathFunc(section.Headers);
                        // 写入文件到临时文件
                        using (var targetStream = System.IO.File.Create(targetFilePath))
                        {
                            // 此方法接收数据不全
                            await section.Body.CopyToAsync(targetStream);

                            //LogInfo($"Copied the uploaded file '{targetFilePath}'");
                        }
                    }
                    // 是否有表单,这一段用于处理所有键值对
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key" value
                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 5120000,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            // 值长度被MultipartBodyLengthLimit强制限制了
                            var value = await streamReader.ReadToEndAsync();//读取流

                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key.ToString(), value);
                            LogInfo($"key={key.ToString()} | {value}");

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                // 读取下一个节点头(部分)
                section = await reader.ReadNextSectionAsync();
            }


            //这里绑定表单数据到
            // Bind form data to a model
            //var user = new User();
            //var formValueProvider = new FormValueProvider(
            //    BindingSource.Form,
            //    new FormCollection(formAccumulator.GetResults()),
            //    CultureInfo.CurrentCulture);

            //var bindingSuccessful = await TryUpdateModelAsync(user, prefix: "",
            //    valueProvider: formValueProvider);
            //if (!bindingSuccessful)
            //{
            //    if (!ModelState.IsValid)
            //    {
            //        return BadRequest(ModelState);
            //    }
            //}

            //var uploadedData = new UploadedData()
            //{
            //    Name = user.Name,
            //    Age = user.Age,
            //    Zipcode = user.Zipcode,
            //    FilePath = targetFilePath
            //};
            return(Json("success"));
        }
        public async Task <FormDataUploadAccumulator> UploadFormAsync(MultipartReader reader)
        {
            try
            {
                var section = await reader.ReadNextSectionAsync();

                var filename        = Guid.NewGuid().ToString();
                var formAccumulator = new KeyValueAccumulator();
                using (var destinationStream = await _context.GetBucket().OpenUploadStreamAsync(filename))
                {
                    var id = destinationStream.Id; // the unique Id of the file being uploaded

                    while (section != null)
                    {
                        var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition);

                        if (hasContentDispositionHeader)
                        {
                            if (_requestHelper.HasFileContentDisposition(contentDisposition))
                            {
                                filename = HeaderUtilities.RemoveQuotes(contentDisposition.FileName).ToString();
                                // write the contents of the file to stream using asynchronous Stream methods
                                await section.Body.CopyToAsync(destinationStream);
                            }
                            else if (_requestHelper.HasFormDataContentDisposition(contentDisposition))
                            {
                                // Content-Disposition: form-data; name="key"
                                //
                                // value

                                // Do not limit the key name length here because the
                                // multipart headers length limit is already in effect.
                                var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name).ToString();
                                var encoding = _requestHelper.GetEncoding(section);
                                using (var streamReader = new StreamReader(section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true))
                                {
                                    // The value length limit is enforced by MultipartBodyLengthLimit
                                    var value = await streamReader.ReadToEndAsync();

                                    if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                                    {
                                        value = String.Empty;
                                    }
                                    formAccumulator.Append(key, value);

                                    //if (formAccumulator.ValueCount > 4)//Todo get default value
                                    //{
                                    //    throw new InvalidDataException($"Form key count limit exceeded.");
                                    //}
                                }
                            }
                        }

                        // Drains any remaining section body that has not been consumed and
                        // reads the headers for the next section.
                        section = await reader.ReadNextSectionAsync();
                    }

                    await destinationStream.CloseAsync(); // optional but recommended so Dispose does not block

                    var extension = Path.GetExtension(filename);
                    var newName   = Guid.NewGuid().ToString() + extension;
                    _context.GetBucket().Rename(id, newName);
                    return(new FormDataUploadAccumulator
                    {
                        FileId = id.ToString(),
                        Filename = newName,
                        Accumulator = formAccumulator
                    });
                }
            }
            catch (Exception ex)
            {
                // log or manage the exception
                throw ex;
            }
        }
        public async Task <IActionResult> UploadFile([FromRoute] string username, [FromRoute] string directoryPath)
        {
            //string requestContentType = Request.ContentType;
            //bool hasFormContentType = Request.HasFormContentType;

            // Accumulate all form key-value pairs in the request (in case we want to do something with other form-fields that are not only files)
            KeyValueAccumulator         formAccumulator   = new KeyValueAccumulator();
            Dictionary <string, string> sectionDictionary = new Dictionary <string, string>();

            // get off the boundary appended by the form-post
            string boundary = GetBoundary(Request.ContentType);

            try // FIX THIS HUGE TRY BLOCK
            {
                var reader = new MultipartReader(boundary, Request.Body);
                MultipartSection section = null;

                section = await reader.ReadNextSectionAsync();

                while (section != null)
                {
                    // Get the conten header disposition for checking if we are handling a file-form-field or just any other type of field
                    ContentDispositionHeaderValue contentDisposition;
                    var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

                    if (hasContentDispositionHeader)
                    {
                        if (contentDisposition.IsFileDisposition())
                        {
                            // Fetch data from header (Delete this after we implement authentication)
                            var appId       = Request.Headers["AppId"];
                            var phonenumber = Request.Headers["OwnerPhoneNumber"];
                            var firstname   = Request.Headers["OwnerFirstName"];
                            var lastname    = Request.Headers["OwnerLastName"];

                            // Here we handle file fields
                            string fileName   = contentDisposition.FileName.ToString().Replace(" ", "");
                            string UploadsDir = Path.Combine(appEnv.WebRootPath, $"dataspace/{username}");

                            // If the BASE dir doesn't exist, create it
                            Directory.CreateDirectory(UploadsDir);

                            string physicalPath;
                            string url;
                            // Check for subdir
                            if (String.IsNullOrWhiteSpace(directoryPath))
                            {
                                physicalPath  = Path.Combine(UploadsDir, fileName); // Prepare file name and path for writing
                                url           = $"{Request.Scheme}://{Request.Host}/dataspace/{username}/files/{fileName}";
                                directoryPath = "";
                            }
                            else
                            {
                                physicalPath = Path.Combine(UploadsDir, directoryPath, fileName); // Prepare file name and path for writing
                                url          = $"{Request.Scheme}://{Request.Host}/dataspace/{username}/files/{directoryPath}/{fileName}";
                            }

                            //// We can also use a temp location for now eg. AppData on Windows
                            //var targetFilePath = Path.GetTempFileName();

                            // Createa a stream and write the request (section-field) body/data
                            using (var targetStream = System.IO.File.Create(physicalPath))
                            {
                                // Copy file to disk
                                await section.Body.CopyToAsync(targetStream);


                                // TODO: Generate metadata and save the path into a FileMicroservice with SignalR (db handler)
                                FileDto newFile = new FileDto
                                {
                                    Name         = fileName,
                                    Path         = directoryPath,
                                    Url          = url,
                                    MimeType     = section.ContentType,
                                    FileSizeInKB = (int)(targetStream.Length / 1024) // Test
                                };

                                dataSpaceSignalRClient.SaveFileMetadata(phonenumber, newFile); // rename stuff like this to nodePath
                            }
                        }
                        else if (contentDisposition.IsFormDisposition())
                        {
                            // Remove this (?)
                            // Here we handle other form fields
                            StringSegment fieldName = HeaderUtilities.RemoveQuotes(contentDisposition.Name);

                            FormMultipartSection formMultipartSection = section.AsFormDataSection();
                            string fieldValue = await formMultipartSection.GetValueAsync().ConfigureAwait(false);

                            sectionDictionary.Add(formMultipartSection.Name, fieldValue);

                            using (var streamReader = new StreamReader(section.Body))
                            {
                                if (String.Equals(fieldValue, "undefined", StringComparison.OrdinalIgnoreCase))
                                {
                                    fieldValue = String.Empty;
                                }
                                formAccumulator.Append(fieldName.ToString(), fieldValue);
                            }
                        }
                    }
                    // Read next section/field
                    section = await reader.ReadNextSectionAsync();
                }
            }
            catch (Exception e)
            {
                // handle any unread or errors on errors while streaming and writing received data
                return(BadRequest());
            }

            //// Remove this (?)
            //// Handle all the non-file fields either here, or above while reading the streams already eg. chosen parent directory
            //var result = sectionDictionary;
            //var frmResults = formAccumulator.GetResults();

            return(Ok());
        }
Example #27
0
        public static async Task <FormValueProvider> StreamFile(this HttpRequest request, Stream targetStream)
        {
            if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType))
            {
                throw new Exception($"Expected a multipart request, but got {request.ContentType}");
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var    formAccumulator = new KeyValueAccumulator();
            string targetFilePath  = null;

            var boundary = MultipartRequestHelper.GetBoundary(
                Microsoft.Net.Http.Headers.MediaTypeHeaderValue.Parse(request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, request.Body);

            var section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        await section.Body.CopyToAsync(targetStream);
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key.Value, value); // For .NET Core <2.0 remove ".Value" from key

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            // Bind form data to a model
            var formValueProvider = new FormValueProvider(
                BindingSource.Form,
                new FormCollection(formAccumulator.GetResults()),
                CultureInfo.CurrentCulture);

            return(formValueProvider);
        }
Example #28
0
        private async Task <(MemberDto, ImageDto?)> UploadUserImageMultipartContent(Guid targetUserId, Stream requestBody, byte[] rowVersion, string?contentType, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var now = _systemClock.UtcNow.UtcDateTime;

            var defaultFormOptions = new FormOptions();
            // Create a Collection of KeyValue Pairs.
            var formAccumulator = new KeyValueAccumulator();
            // Determine the Multipart Boundary.
            var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(contentType), defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader   = new MultipartReader(boundary, requestBody);
            var section  = await reader.ReadNextSectionAsync(cancellationToken);

            ImageDto? imageDto = null;
            MemberDto userDto  = new MemberDto();

            // Loop through each 'Section', starting with the current 'Section'.
            while (section != null)
            {
                // Check if the current 'Section' has a ContentDispositionHeader.
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        if (contentDisposition != null)
                        {
                            var sectionFileName = contentDisposition.FileName.Value;
                            // use an encoded filename in case there is anything weird
                            var encodedFileName = WebUtility.HtmlEncode(Path.GetFileName(sectionFileName));

                            // read the section filename to get the content type
                            var fileExtension = Path.GetExtension(sectionFileName);

                            // now make it unique
                            var uniqueFileName = $"{Guid.NewGuid()}{fileExtension}";

                            if (!_acceptedFileTypes.Contains(fileExtension.ToLower()))
                            {
                                _logger.LogError("file extension:{0} is not an accepted image file", fileExtension);
                                throw new ValidationException("Image", "The image is not in an accepted format");
                            }

                            var compressedImage = _imageService.TransformImageForAvatar(section.Body);

                            try
                            {
                                await _blobStorageProvider.UploadFileAsync(compressedImage.Image, uniqueFileName,
                                                                           MimeTypesMap.GetMimeType(encodedFileName), cancellationToken);
                            }
                            catch (Exception ex)
                            {
                                _logger.LogError(ex, "An error occurred uploading file to blob storage");
                                throw;
                            }

                            // trick to get the size without reading the stream in memory
                            var size = section.Body.Position;

                            imageDto = new ImageDto
                            {
                                FileSizeBytes = size,
                                FileName      = uniqueFileName,
                                Height        = compressedImage.Height,
                                Width         = compressedImage.Width,
                                IsDeleted     = false,
                                MediaType     = compressedImage.MediaType,
                                CreatedBy     = targetUserId,
                                CreatedAtUtc  = now
                            };

                            var imageValidator        = new ImageValidator(MaxFileSizeBytes);
                            var imageValidationResult = await imageValidator.ValidateAsync(imageDto, cancellationToken);

                            if (imageValidationResult.Errors.Count > 0)
                            {
                                await _blobStorageProvider.DeleteFileAsync(uniqueFileName);

                                _logger.LogError("File size:{0} is greater than the max allowed size:{1}", size, MaxFileSizeBytes);
                                throw new ValidationException(imageValidationResult);
                            }
                        }
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // if for some reason other form data is sent it would get processed here
                        var key = HeaderUtilities.RemoveQuotes(contentDisposition?.Name.ToString().ToLowerInvariant());

                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true))
                        {
                            var value = await streamReader.ReadToEndAsync();

                            if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = string.Empty;
                            }
                            formAccumulator.Append(key.Value, value);
                            if (formAccumulator.ValueCount > defaultFormOptions.ValueCountLimit)
                            {
                                _logger.LogError("UserEdit: Form key count limit {0} exceeded.", defaultFormOptions.ValueCountLimit);
                                throw new FormatException($"Form key count limit { defaultFormOptions.ValueCountLimit } exceeded.");
                            }
                        }
                    }
                }
                // Begin reading the next 'Section' inside the 'Body' of the Request.
                section = await reader.ReadNextSectionAsync(cancellationToken);
            }

            if (formAccumulator.HasValues)
            {
                var formValues = formAccumulator.GetResults();

                // Check if users been updated
                // Unable to place in controller due to disabling form value model binding
                var user = await _userCommand.GetMemberAsync(targetUserId, cancellationToken);

                if (!user.RowVersion.SequenceEqual(rowVersion))
                {
                    _logger.LogError($"Precondition Failed: UpdateUserAsync - User:{0} has changed prior to submission", targetUserId);
                    throw new PreconditionFailedExeption("Precondition Failed: User has changed prior to submission");
                }

                var firstNameFound = formValues.TryGetValue("firstName", out var firstName);
                if (firstNameFound is false || string.IsNullOrEmpty(firstName))
                {
                    throw new ArgumentNullException($"First name was not provided");
                }
                formValues.TryGetValue("lastName", out var surname);

                var pronoundsFound = formValues.TryGetValue("pronouns", out var pronouns);
                if (pronoundsFound is false)
                {
                    throw new ArgumentNullException($"Pronouns were not provided");
                }

                formValues.TryGetValue("imageid", out var image);

                var imageId = Guid.TryParse(image, out var imageGuid) ? (Guid?)imageGuid : null;
                if (imageId.HasValue)
                {
                    if (imageId == new Guid())
                    {
                        throw new ArgumentOutOfRangeException($"Incorrect Id provided");
                    }
                }

                userDto = new MemberDto
                {
                    Id            = targetUserId,
                    FirstName     = firstName,
                    Surname       = surname,
                    Pronouns      = pronouns,
                    ImageId       = imageId,
                    ModifiedAtUTC = now,
                    ModifiedBy    = targetUserId,
                };
            }

            return(userDto, imageDto);
        }
Example #29
0
        public async Task <IActionResult> StreamingUpload(Int32 id)
        {
            Debug.WriteLine("In Streaming Upload for Trip Number: " + id);

            if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
            {
                return(BadRequest($"Expected a multipart request, but got {Request.ContentType}"));
            }

            // Used to accumulate all the form url encoded key value pairs in the
            // request.
            var    formAccumulator = new KeyValueAccumulator();
            string targetFilePath  = null;

            var boundary = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(Request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader = new MultipartReader(boundary, HttpContext.Request.Body);

            var section = await reader.ReadNextSectionAsync();

            string   newFileName  = "";
            DateTime FileDateTime = new DateTime();

            while (section != null)
            {
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        //targetFilePath = Path.GetTempFileName();

                        string fileName = contentDisposition.FileName.ToString().Trim('"');
                        newFileName    = FileHelper.newFileName(id, fileName, out FileDateTime);
                        targetFilePath = Path.Combine(_newPath, newFileName);
                        using (var targetStream = System.IO.File.Create(targetFilePath))
                        {
                            await section.Body.CopyToAsync(targetStream);

                            //  _logger.LogInformation($"Copied the uploaded file '{targetFilePath}'");
                        }
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // Content-Disposition: form-data; name="key"
                        //
                        // value

                        // Do not limit the key name length here because the
                        // multipart headers length limit is already in effect.
                        var key      = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(
                                   section.Body,
                                   encoding,
                                   detectEncodingFromByteOrderMarks: true,
                                   bufferSize: 1024,
                                   leaveOpen: true))
                        {
                            // The value length limit is enforced by MultipartBodyLengthLimit
                            var value = await streamReader.ReadToEndAsync();

                            if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = String.Empty;
                            }
                            formAccumulator.Append(key.ToString(), value);

                            if (formAccumulator.ValueCount > _defaultFormOptions.ValueCountLimit)
                            {
                                throw new InvalidDataException($"Form key count limit {_defaultFormOptions.ValueCountLimit} exceeded.");
                            }
                        }
                    }
                }

                //add the Trip File Object to the database
                //TripFile TripFileItem = new TripFile
                //{
                //    TripID = id,
                //    TripFileName = newFileName,
                //    FilePath = targetFilePath,
                //    FileDateTime = FileDateTime.ToString()
                //};
                //_context.Add(TripFileItem);
                //_context.SaveChanges();

                // Drains any remaining section body that has not been consumed and
                // reads the headers for the next section.
                section = await reader.ReadNextSectionAsync();
            }

            /// Bind form data to a model
            var formValueProvider = new FormValueProvider(
                BindingSource.Form,
                new FormCollection(formAccumulator.GetResults()),
                CultureInfo.CurrentCulture);

            return(new JsonResult(formValueProvider));
        }
Example #30
0
        /// based on microsoft example https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/mvc/models/file-uploads/samples/
        /// and large file streaming example https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-5.0#upload-large-files-with-streaming
        private async Task <(GroupDto, ImageDto?)> UploadGroupImageMultipartContent(GroupData groupData, Guid userId, string slug, Stream requestBody, byte[] rowVersion, string?contentType, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Check if HttpRequest (Form Data) is a Multipart Content Type
            if (!MultipartRequestHelper.IsMultipartContentType(contentType))
            {
                throw new InvalidDataException($"Expected a multipart request, but got {contentType}");
            }

            var now = _systemClock.UtcNow.UtcDateTime;

            var defaultFormOptions = new FormOptions();
            // Create a Collection of KeyValue Pairs.
            var formAccumulator = new KeyValueAccumulator();
            // Determine the Multipart Boundary.
            var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(contentType), defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader   = new MultipartReader(boundary, requestBody);
            var section  = await reader.ReadNextSectionAsync(cancellationToken);

            ImageDto?imageDto = null;
            GroupDto groupDto = new GroupDto();

            // Loop through each 'Section', starting with the current 'Section'.
            while (section != null)
            {
                // Check if the current 'Section' has a ContentDispositionHeader.
                var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var contentDisposition);
                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        if (contentDisposition != null)
                        {
                            var sectionFileName = contentDisposition.FileName.Value;
                            // use an encoded filename in case there is anything weird
                            var encodedFileName = WebUtility.HtmlEncode(Path.GetFileName(sectionFileName));

                            // read the section filename to get the content type
                            var fileExtension = Path.GetExtension(sectionFileName);

                            // now make it unique
                            var uniqueFileName = $"{Guid.NewGuid()}{fileExtension}";

                            if (!_acceptedFileTypes.Contains(fileExtension.ToLower()))
                            {
                                _logger.LogError("file extension:{0} is not an accepted image file", fileExtension);
                                throw new ValidationException("Image", "The image is not in an accepted format");
                            }

                            var compressedImage = _imageService.TransformImageForGroupHeader(section.Body);

                            try
                            {
                                await _blobStorageProvider.UploadFileAsync(compressedImage.Image, uniqueFileName,
                                                                           MimeTypesMap.GetMimeType(encodedFileName), cancellationToken);
                            }
                            catch (Exception ex)
                            {
                                _logger.LogError(ex, "An error occurred uploading file to blob storage");
                                throw;
                            }

                            // trick to get the size without reading the stream in memory
                            var size = section.Body.Position;

                            // TODO MimeDetective does not work when stream has already been uploaded - figure out a solution
                            //if (fileContentTypeMatchesExtension is false)
                            //{
                            //    await _blobStorageProvider.DeleteFileAsync(uniqueFileName);
                            //    _logger.LogError("File extension:{0} does not match the file signature", fileExtension);
                            //    throw new FormatException("File extension} does not match the file signature");
                            //}

                            imageDto = new ImageDto
                            {
                                FileSizeBytes = size,
                                FileName      = uniqueFileName,
                                Height        = compressedImage.Height,
                                Width         = compressedImage.Width,
                                IsDeleted     = false,
                                MediaType     = compressedImage.MediaType,
                                CreatedBy     = userId,
                                CreatedAtUtc  = now
                            };

                            var imageValidator        = new ImageValidator(MaxFileSizeBytes);
                            var imageValidationResult = await imageValidator.ValidateAsync(imageDto, cancellationToken);

                            if (imageValidationResult.Errors.Count > 0)
                            {
                                await _blobStorageProvider.DeleteFileAsync(uniqueFileName);

                                _logger.LogError("File size:{0} is greater than the max allowed size:{1}", size, MaxFileSizeBytes);
                                throw new ValidationException(imageValidationResult);
                            }
                        }
                    }
                    else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
                    {
                        // if for some reason other form data is sent it would get processed here
                        var key = HeaderUtilities.RemoveQuotes(contentDisposition?.Name.ToString().ToLowerInvariant());

                        var encoding = GetEncoding(section);
                        using (var streamReader = new StreamReader(section.Body, encoding, detectEncodingFromByteOrderMarks: true, bufferSize: 1024, leaveOpen: true))
                        {
                            var value = await streamReader.ReadToEndAsync();

                            if (string.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
                            {
                                value = string.Empty;
                            }
                            formAccumulator.Append(key.Value, value);
                            if (formAccumulator.ValueCount > defaultFormOptions.ValueCountLimit)
                            {
                                _logger.LogError("GroupEdit: Form key count limit {0} exceeded.", defaultFormOptions.ValueCountLimit);
                                throw new FormatException($"Form key count limit { defaultFormOptions.ValueCountLimit } exceeded.");
                            }
                        }
                    }
                }
                // Begin reading the next 'Section' inside the 'Body' of the Request.
                section = await reader.ReadNextSectionAsync(cancellationToken);
            }

            if (formAccumulator.HasValues)
            {
                var formValues = formAccumulator.GetResults();

                // Get values from multipart form
                var nameFound = formValues.TryGetValue("name", out var name);
                if (nameFound is false)
                {
                    throw new ValidationException("Name", "Name was not provided");
                }
                var straplineFound = formValues.TryGetValue("strapline", out var strapline);
                if (straplineFound is false)
                {
                    throw new ValidationException("Strapline", "Strapline was not provided");
                }

                formValues.TryGetValue("themeid", out var theme);
                if (Guid.TryParse(theme, out var themeId) is false || themeId == new Guid())
                {
                    throw new ValidationException(nameof(GroupDto.ThemeId), "Theme was not provided");
                }

                formValues.TryGetValue("imageid", out var image);
                var imageId = Guid.TryParse(image, out var imageGuid) ? (Guid?)imageGuid : null;
                if (imageId.HasValue)
                {
                    if (imageId == new Guid())
                    {
                        throw new ArgumentOutOfRangeException($"Incorrect Id provided");
                    }
                }

                formValues.TryGetValue("isPublic", out var publicGroup);
                var isPublic = bool.TryParse(publicGroup, out var isPublicBool) ? isPublicBool : false;
                if (!groupData.IsPublic)
                {
                    if (isPublic != groupData.IsPublic)
                    {
                        throw new ValidationException("isPublic", "Cannot make a private group public");
                    }
                }

                groupDto = new GroupDto
                {
                    Slug          = slug,
                    Name          = _htmlSanitizer.Sanitize(name),
                    Strapline     = _htmlSanitizer.Sanitize(strapline),
                    ThemeId       = themeId,
                    ImageId       = imageId,
                    ModifiedBy    = userId,
                    ModifiedAtUtc = now,
                    IsPublic      = isPublic,
                    RowVersion    = rowVersion
                };
            }
            return(groupDto, imageDto);
        }