Beispiel #1
0
        public static async Task <FormValueProvider> StreamFilesModel(this HttpRequest request, Func <IFormFile, Task> func)
        {
            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();

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

                if (hasHeader && contentDispositionHeader.IsFileDisposition())
                {
                    FileMultipartSection fileSection = section.AsFileSection();

                    // process file stream
                    await func(new MultipartFile(fileSection.FileStream, fileSection.Name, fileSection.FileName) {
                        ContentType        = fileSection.Section.ContentType,
                        ContentDisposition = fileSection.Section.ContentDisposition
                    });
                }
                else if (hasHeader && contentDispositionHeader.IsFormDisposition())
                {
                    // 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(contentDispositionHeader.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.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 = request.Body.CanSeek && request.Body.Position == request.Body.Length ? null : await reader.ReadNextSectionAsync();
            }
            // Bind form data to a model
            var formValueProvider = new FormValueProvider(BindingSource.Form, new FormCollection(formAccumulator.GetResults()), CultureInfo.CurrentCulture);

            return(formValueProvider);
        }
        /// <summary>
        /// extract a file from the form section and saves it
        /// </summary>
        /// <param name="fileSection"></param>
        /// <returns>saved file path</returns>
        private static async Task <string> SaveFile(FileMultipartSection fileSection, string outputDir)
        {
            var invalids = Path.GetInvalidFileNameChars();
            var fileName = string.Join("_", fileSection.FileName.Split(invalids, StringSplitOptions.RemoveEmptyEntries)).TrimEnd('.');
            var path     = Path.Combine(outputDir, fileName);

            using (var stream = new FileStream(path, FileMode.Append))
                await fileSection.FileStream.CopyToAsync(stream);
            return(path);
        }
Beispiel #3
0
        public static FileInfoParam GetFileInfo(FileMultipartSection fileMultipartSection)
        {
            FileInfoParam fileInfo = new FileInfoParam()
            {
                FileName = fileMultipartSection.FileName,
                // FileName = $"{Guid.NewGuid().ToString("N")}{Path.GetExtension(fileMultipartSection.FileName)}",
                Size       = fileMultipartSection.FileStream.Length,
                FileExtion = Path.GetExtension(fileMultipartSection.FileName)
            };

            fileInfo.FileType = GetFileType(fileInfo.FileExtion);
            return(fileInfo);
        }
Beispiel #4
0
        /// <summary>
        /// 接收文件、保存记录
        /// </summary>
        /// <param name="p_section"></param>
        /// <returns></returns>
        async Task <FileDesc> ReceiveFile(FileMultipartSection p_section)
        {
            FileDesc desc = new FileDesc();

            desc.ID   = Kit.NewID;
            desc.Name = p_section.FileName;
            if (long.TryParse(_context.Request.Headers["uid"], out var id))
            {
                desc.Uploader = id;
            }
            desc.Info = p_section.Name;

            // 扩展名
            int    pt  = desc.Name.LastIndexOf('.');
            string ext = pt > -1 ? desc.Name.Substring(pt).ToLower() : "";

            // 根据文件名获取两级目录
            string dir = GetDir(desc.Name);

            desc.Path = Path.Combine(_volume, dir, desc.ID + ext).Replace('\\', '/');
            EnsurePathExist(dir);
            string fullPath = Path.Combine(Cfg.Root, _volume, dir, desc.ID + ext);

            _result.Add(desc.Path);

            try
            {
                using (var writeStream = File.Create(fullPath))
                {
                    // FileStream 类型为 MultipartReaderStream
                    await p_section.FileStream.CopyToAsync(writeStream, _bufferSize, _context.RequestAborted);

                    desc.Size = writeStream.Length;
                }
                await _db.Exec("上传文件", desc);
            }
            catch
            {
                FileInfo fi = new FileInfo(fullPath);
                if (fi.Exists)
                {
                    try
                    {
                        fi.Delete();
                    }
                    catch { }
                }
                throw;
            }
            return(desc);
        }
Beispiel #5
0
        public async Task <IActionResult> Upload()
        {
            MediaTypeHeaderValue mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(Request.ContentType);

            string boundary = HeaderUtilities.RemoveQuotes(mediaTypeHeaderValue.Boundary).ToString();

            MultipartReader reader = new MultipartReader(boundary, Request.Body, 64 * 1024);

            MultipartSection section = await reader.ReadNextSectionAsync();

            while (section != null)
            {
                ContentDispositionHeaderValue contentDispositionHeaderValue = section.GetContentDispositionHeader();

                if (!contentDispositionHeaderValue.IsFileDisposition())
                {
                    throw new InvalidOperationException("Only file disposition supported.");
                }

                FileMultipartSection fileSection = section.AsFileSection();

                int bufferSize = 64 * 1024;

                string fileName = Path.Combine(_targetFilePath, Path.GetFileName(fileSection.FileName));

                using (FileStream targetStream = System.IO.File.Create(fileName, bufferSize)) {
                    await fileSection.FileStream.CopyToAsync(targetStream);

                    _logger.LogInformation($"File uploaded to: {fileName}");
                }

                section = await reader.ReadNextSectionAsync();
            }

            return(Ok());
        }
Beispiel #6
0
        private async Task <IFormCollection> InnerReadFormAsync(CancellationToken cancellationToken)
        {
            if (!HasFormContentType)
            {
                throw new InvalidOperationException("Incorrect Content-Type: " + _request.ContentType);
            }

            cancellationToken.ThrowIfCancellationRequested();

            //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
                        ContentDispositionHeaderValue contentDisposition;
                        ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);

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

                            FormFile file;
                            if (section.Body.CanSeek)
                            {
                                // Find the end
                                await section.Body.ConsumeAsync(cancellationToken);

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


                                if (section.BaseStreamOffset.HasValue)
                                {
                                    // Relative reference to buffered request body
                                    file = new StreamFormFile(_request.Body, section.BaseStreamOffset.Value, section.Body.Length, name, fileName);
                                }
                                else
                                {
                                    // Individually buffered file body
                                    file = new StreamFormFile(section.Body, 0, section.Body.Length, name, fileName);
                                }
                                file.Headers = new HeaderDictionary(section.Headers);
                            }
                            else
                            {
                                //// Enable buffering for the file if not already done for the full body
                                //section.EnableRewind(
                                //    _request.HttpContext.Response.RegisterForDispose,
                                //    _options.MemoryBufferThreshold, _options.MultipartBodyLengthLimit);

                                //read all bytes.
                                var bytes = await section.Body.ReadAllBytesAsync(cancellationToken);

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

                                if (section.BaseStreamOffset.HasValue)
                                {
                                    // Relative reference to buffered request body
                                    file = new BufferedFormFile(new ArraySegment <byte>(bytes, (int)section.BaseStreamOffset.Value, (int)section.Body.Length), name, fileName);
                                }
                                else
                                {
                                    // Individually buffered file body
                                    file = new BufferedFormFile(new ArraySegment <byte>(bytes, 0, (int)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 mulipart 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);
        }
        public static async Task <FormValueProvider> StreamFile(this HttpRequest request, Stream targetStream,
                                                                string path)
        {
            file_name = new List <string>();
            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 = ;
            string targetFilePath = null;
            var    boundary       = MultipartRequestHelper.GetBoundary(
                MediaTypeHeaderValue.Parse(request.ContentType),
                _defaultFormOptions.MultipartBoundaryLengthLimit);
            var reader  = new MultipartReader(boundary, request.Body);
            var section = await reader.ReadNextSectionAsync();

            //file_name.Clear();
            while (section != null)
            {
                ContentDispositionHeaderValue contentDisposition;
                var hasContentDispositionHeader =
                    ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
                string rt = contentDisposition.FileName.ToString();
                file_name.Add(rt);
                if (hasContentDispositionHeader)
                {
                    if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
                    {
                        FileMultipartSection currentFile = section.AsFileSection();
                        string filePath = Path.Combine(path, currentFile.FileName);

                        using (targetStream = File.Create(filePath))
                        {
                            await section.Body.CopyToAsync(targetStream).ConfigureAwait(false);
                        }
                    }
                    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,
                                   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);
        }
Beispiel #8
0
        public async Task <ParseBodyAndSavePacketsResult> ParseBodyAndSavePackets(MessageHeaders messageHeaders, HttpRequest request)
        {
            var cancellationToken = request.HttpContext.RequestAborted;

            cancellationToken.ThrowIfCancellationRequested();

            var    format   = messageHeaders.Format ?? TransportConstants.RequestFormDataFormat;
            string boundary = null;

            if (format == TransportConstants.RequestFormDataFormat)
            {
                int fileSectionBufferSize = 81920;

                // если данные formdata упорядочены в потоке запроса (бинарные данные должны идти после большинства метаданных о пакете)
                if (messageHeaders.Hints?.Contains(MessageHints.OrderedFormData) == true)
                {
                    var indexToPacketDataItem    = new Dictionary <int, PacketFormDataItem>();
                    var indexToPacketBytes       = new Dictionary <int, byte[]>();
                    var indexToConfigurationItem = new Dictionary <int, ConfigurationRequestDataItem>();

                    if (MediaTypeHeaderValue.TryParse(request.ContentType, out var contentType))
                    {
                        boundary = HeaderUtilities.GetBoundary(contentType, 70);
                    }

                    var multipartReader = new MultipartReader(boundary, request.Body)
                    {
                        //ValueCountLimit = _options.ValueCountLimit,
                        //KeyLengthLimit = _options.KeyLengthLimit,
                        //ValueLengthLimit = _options.ValueLengthLimit,

                        HeadersCountLimit  = int.MaxValue,
                        HeadersLengthLimit = int.MaxValue,
                        BodyLengthLimit    = long.MaxValue,
                    };

                    //PacketFormDataItem current = null;
                    //byte[] currentBytes = null;
                    var agentId = messageHeaders.GetAgentIdData();
                    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);

                            var name     = fileSection.Name;
                            var fileName = fileSection.FileName;
                            var packetId = fileSection.FileName;
                            var result   = GetFormPathDataFromEntry(name);
                            if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataPacketsProp)
                            {
                                if (int.TryParse(result.Parts[1], out var index))
                                {
                                    var item        = indexToPacketDataItem[index];
                                    var providerKey = item.ProviderKey;

                                    var packetItem = indexToPacketDataItem[index];
                                    if (packetItem.PacketId != packetId)
                                    {
                                        throw new InvalidDataException($"Incorrect format for form-data message. Section {name} has invalid FileName.");
                                    }

                                    var bytes = await ReadToEnd(fileSection.FileStream, fileSectionBufferSize, cancellationToken);

                                    indexToPacketBytes.Add(index, bytes);
                                }
                                else
                                {
                                    throw new InvalidDataException($"Incorrect format for form-data message. Section {name} does not have index suffix.");
                                }
                            }
                            else
                            {
                                throw new InvalidDataException($"Incorrect format for form-data message. Section {name} incorrect.");
                            }
                        }
                        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();

                            var result = GetFormPathDataFromEntry(key);
                            if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataPacketsProp)
                            {
                                if (int.TryParse(result.Parts[1], out var index))
                                {
                                    if (!indexToPacketDataItem.TryGetValue(index, out var dataItem))
                                    {
                                        //// сохраняем предыдущий
                                        //if (current != null)
                                        //{
                                        //    await this.packetsStore.AddIfNotExistsPacketPartAsync(agentId, this.CreateAddPacketRequest(current, currentBytes));
                                        //}

                                        dataItem = new PacketFormDataItem();
                                        indexToPacketDataItem.Add(index, dataItem);
                                    }

                                    if (!dataItem.FillProperty(result.Parts[2], value))
                                    {
                                        throw new InvalidDataException($"Incorrect format for form-data message. Section {key} incorrect.");
                                    }
                                }
                                else
                                {
                                    throw new InvalidDataException($"Incorrect format for form-data message. Section {key} does not have index suffix.");
                                }
                            }
                            else if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataConfigurationProp)
                            {
                                if (int.TryParse(result.Parts[1], out var index))
                                {
                                    if (!indexToConfigurationItem.TryGetValue(index, out var dataItem))
                                    {
                                        dataItem = new ConfigurationRequestDataItem();
                                        indexToConfigurationItem.Add(index, dataItem);
                                    }

                                    if (!dataItem.FillProperty(result.Parts[2], value))
                                    {
                                        throw new InvalidDataException($"Incorrect format for form-data message. Section {key} incorrect.");
                                    }
                                }
                                else
                                {
                                    throw new InvalidDataException($"Incorrect format for form-data message. Section {key} does not have index suffix.");
                                }
                            }
                            else
                            {
                                // ignore or throw?
                            }

                            //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);
                    }

                    // сохраняем все
                    var addResult = indexToPacketDataItem.Any()
                                ? await this.packetsStore.AddIfNotExistsPacketsPartsAsync(agentId, indexToPacketDataItem.Select(x =>
                    {
                        var bytes = indexToPacketBytes[x.Key];
                        return(this.CreateAddPacketRequest(agentId, x.Value, bytes));
                    }).ToList())
                                : AddAddPacketsPartsResult.EmptyResult();

                    return(new ParseBodyAndSavePacketsResult
                    {
                        TransferedPackets = indexToPacketDataItem.Values
                                            .Select(x => {
                            var fromAddResult = addResult.Results.Single(r => r.Request.PacketId == x.PacketId);
                            return new TransferedPacketResponse
                            {
                                PacketId = x.PacketId,
                                ProviderKey = x.ProviderKey,
                                //AgentIdData = agentId,
                                Result = fromAddResult.Success
                                                ? TransferedProcessingResult.Saved
                                                : TransferedProcessingResult.Error,
                                StorageToken = fromAddResult.StorageToken,
                                Id = fromAddResult.Id,
                            };
                        }).ToList(),
                        ConfigurationsStats = indexToConfigurationItem.Values,
                    });
                }
                else
                {
                    var indexToPacketDataItem    = new Dictionary <string, PacketFormDataItem>();
                    var indexToPacketBytes       = new Dictionary <string, byte[]>();
                    var indexToConfigurationItem = new Dictionary <string, ConfigurationRequestDataItem>();
                    var agentId = messageHeaders.GetAgentIdData();

                    foreach (var item in request.Form)
                    {
                        var key   = item.Key;
                        var value = item.Value;

                        var result = GetFormPathDataFromEntry(key);
                        if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataPacketsProp)
                        {
                            var index = result.Parts[1];
                            if (!indexToPacketDataItem.TryGetValue(index, out var dataItem))
                            {
                                dataItem = new PacketFormDataItem();
                                indexToPacketDataItem.Add(index, dataItem);
                            }

                            if (!dataItem.FillProperty(result.Parts[2], value))
                            {
                                throw new InvalidDataException($"Incorrect format for form-data message. Section {key} incorrect.");
                            }
                        }

                        if (result != null && result.Parts.Count == 3 && result.Parts[0] == TransportConstants.FormDataConfigurationProp)
                        {
                            var index = result.Parts[1];
                            if (!indexToConfigurationItem.TryGetValue(index, out var dataItem))
                            {
                                dataItem = new ConfigurationRequestDataItem();
                                indexToConfigurationItem.Add(index, dataItem);
                            }

                            if (!dataItem.FillProperty(result.Parts[2], value))
                            {
                                throw new InvalidDataException($"Incorrect format for form-data message. Section {key} incorrect.");
                            }
                        }
                    }

                    foreach (var file in request.Form.Files)
                    {
                        var pair = indexToPacketDataItem
                                   .FirstOrDefault(x => x.Value.PacketId == file.FileName);

                        if (default(KeyValuePair <string, PacketFormDataItem>).Equals(pair))
                        {
                            var item        = pair.Value;
                            var providerKey = item.ProviderKey;
                            var packetId    = item.PacketId;

                            using (var fileStream = file.OpenReadStream())
                            {
                                var currentBytes = await ReadToEnd(fileStream, fileSectionBufferSize, cancellationToken);

                                indexToPacketBytes.Add(pair.Key, currentBytes);
                            }
                        }
                    }

                    // сохраняем все
                    var addResult = indexToPacketDataItem.Any()
                                ? await this.packetsStore.AddIfNotExistsPacketsPartsAsync(agentId, indexToPacketDataItem.Select(x =>
                    {
                        var bytes = indexToPacketBytes[x.Key];
                        return(this.CreateAddPacketRequest(agentId, x.Value, bytes));
                    }).ToList())
                                : AddAddPacketsPartsResult.EmptyResult();

                    return(new ParseBodyAndSavePacketsResult
                    {
                        TransferedPackets = indexToPacketDataItem.Values
                                            .Select(x =>
                        {
                            var fromAddResult = addResult.Results
                                                .Single(r => r.Request.PacketId == x.PacketId);
                            return new TransferedPacketResponse
                            {
                                PacketId = x.PacketId,
                                ProviderKey = x.ProviderKey,
                                //AgentIdData = agentId,
                                Result = fromAddResult.Success
                                                                    ? TransferedProcessingResult.Saved
                                                                    : TransferedProcessingResult.Error,
                                StorageToken = fromAddResult.StorageToken,
                                Id = fromAddResult.Id,
                            };
                        }).ToList(),
                        ConfigurationsStats = indexToConfigurationItem.Values,
                    });
                }
            }
            else
            {
                throw new NotSupportedException($"format {format} is not supported");
            }
        }
        private async Task <FormCollection> GetMultipartFormCollection(ModificationContext modificationContext)
        {
            var formAccumulator = new KeyValueAccumulator();

            var multipartReader = new MultipartReader(_originalBoundary, modificationContext.ContentStream)
            {
                HeadersCountLimit  = _options.Value.FormOptions.MultipartHeadersCountLimit,
                HeadersLengthLimit = _options.Value.FormOptions.MultipartHeadersLengthLimit,
                BodyLengthLimit    = _options.Value.FormOptions.MultipartBodyLengthLimit,
            };

            var section = await multipartReader.ReadNextSectionAsync();

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

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

                    await section.Body.DrainAsync(new System.Threading.CancellationToken());

                    FormFile file;

                    if (contentDisposition.FileName == "\"\"")
                    {
                        file = new FormFile(
                            section.Body,
                            0,
                            section.Body.Length,
                            fileSection.Name,
                            fileSection.FileName
                            );
                    }
                    else
                    {
                        file = new FormFile(
                            section.BaseStreamOffset.HasValue ? modificationContext.ContentStream : section.Body,
                            section.BaseStreamOffset.HasValue ? section.BaseStreamOffset.Value : 0,
                            section.Body.Length,
                            fileSection.Name,
                            fileSection.FileName
                            );
                    }

                    file.Headers = new HeaderDictionary(section.Headers);

                    if (_formFiles == null)
                    {
                        _formFiles = new FormFileCollection();
                    }

                    if (_formFiles.Count >= _options.Value.FormOptions.ValueCountLimit)
                    {
                        throw new InvalidDataException($"Form value count limit {_options.Value.FormOptions.ValueCountLimit} exceeded.");
                    }

                    _formFiles.Add(file);
                }
                else if (contentDisposition.IsFormDisposition())
                {
                    var formDataSection = new FormMultipartSection(section, contentDisposition);

                    var value = await formDataSection.GetValueAsync();

                    formAccumulator.Append(formDataSection.Name, value);

                    if (formAccumulator.ValueCount > _options.Value.FormOptions.ValueCountLimit)
                    {
                        throw new InvalidDataException($"Form value count limit {_options.Value.FormOptions.ValueCountLimit} exceeded.");
                    }
                }
                else
                {
                    throw new InvalidDataException($"Unrecognized content-disposition for this section: {section.ContentDisposition}");
                }

                section = await multipartReader.ReadNextSectionAsync();
            }

            if (formAccumulator.HasValues || _formFiles != null)
            {
                return(new FormCollection(formAccumulator.HasValues ? formAccumulator.GetResults() : null, _formFiles));
            }
            else
            {
                return(null);
            }
        }
Beispiel #10
0
        public async Task <IActionResult> Upload()
        {
            string multipartBoundary = Request.GetMultipartBoundary();

            if (string.IsNullOrEmpty(multipartBoundary))
            {
                Response.StatusCode = 400;

                return(Json(new UploadResult
                {
                    Succeeded = false,
                    Description = $"Expected a multipart request, but got '{Request.ContentType}'."
                }));
            }

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

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

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

                if (fileSection != null)
                {
                    string fileName = fileSection.FileName;
                    fileExtension = Path.GetExtension(fileName);
                    string targetFolderPath = Path.Combine(_hostingEnvironment.WebRootPath, _appSettings.UploadsFolder, userId);
                    string 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
                {
                    FormMultipartSection formSection = section.AsFormDataSection();

                    if (formSection != null)
                    {
                        string name  = formSection.Name;
                        string 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();
            }

            var uploadResult = new UploadResult
            {
                Succeeded   = true,
                Description = "File was uploaded successfully",
                FileUrl     = $"{_appSettings.Domain}/{_appSettings.UploadsFolder}/{userId}/{fileGuid}{fileExtension}",
                FileName    = $"{fileGuid}{fileExtension}"
            };

            return(Json(uploadResult));
        }