Exemple #1
0
        public override async Task ExecuteResultAsync(IWebDavResponse response, CancellationToken ct)
        {
            await base.ExecuteResultAsync(response, ct).ConfigureAwait(false);

            response.Headers["Accept-Ranges"] = new[] { "bytes" };

            var properties = await _document.GetProperties(response.Dispatcher).ToList(ct).ConfigureAwait(false);

            var etagProperty = properties.OfType <GetETagProperty>().FirstOrDefault();

            if (etagProperty != null)
            {
                var propValue = await etagProperty.GetValueAsync(ct).ConfigureAwait(false);

                response.Headers["ETag"] = new[] { propValue.ToString() };
            }

            if (!_returnFile)
            {
                var lastModifiedProp = properties.OfType <LastModifiedProperty>().FirstOrDefault();
                if (lastModifiedProp != null)
                {
                    var propValue = await lastModifiedProp.GetValueAsync(ct).ConfigureAwait(false);

                    response.Headers["Last-Modified"] = new[] { propValue.ToString("R") };
                }

                return;
            }

            var views = new List <StreamView>();

            try
            {
                foreach (var rangeItem in _rangeItems)
                {
                    var baseStream = await _document.OpenReadAsync(ct).ConfigureAwait(false);

                    var streamView = await StreamView
                                     .CreateAsync(baseStream, rangeItem.From, rangeItem.Length, ct)
                                     .ConfigureAwait(false);

                    views.Add(streamView);
                }

                string contentType;
                var    contentTypeProp = properties.OfType <GetContentTypeProperty>().FirstOrDefault();
                if (contentTypeProp != null)
                {
                    contentType = await contentTypeProp.GetValueAsync(ct).ConfigureAwait(false);
                }
                else
                {
                    contentType = MimeTypesMap.DefaultMimeType;
                }

                HttpContent content;
                if (_rangeItems.Count == 1)
                {
                    // No multipart content
                    var rangeItem  = _rangeItems.Single();
                    var streamView = views.Single();
                    content = new StreamContent(streamView);
                    try
                    {
                        content.Headers.ContentRange  = new ContentRangeHeaderValue(rangeItem.From, rangeItem.To, _document.Length);
                        content.Headers.ContentLength = rangeItem.Length;
                    }
                    catch
                    {
                        content.Dispose();
                        throw;
                    }

                    content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType);
                }
                else
                {
                    // Multipart content
                    var multipart = new MultipartContent("byteranges");
                    try
                    {
                        var index = 0;
                        foreach (var rangeItem in _rangeItems)
                        {
                            var streamView  = views[index++];
                            var partContent = new StreamContent(streamView);
                            partContent.Headers.ContentRange  = new ContentRangeHeaderValue(rangeItem.From, rangeItem.To, _document.Length);
                            partContent.Headers.ContentType   = MediaTypeHeaderValue.Parse(contentType);
                            partContent.Headers.ContentLength = rangeItem.Length;
                            multipart.Add(partContent);
                        }
                    }
                    catch
                    {
                        multipart.Dispose();
                        throw;
                    }

                    content = multipart;
                }

                using (content)
                {
                    await SetPropertiesToContentHeaderAsync(content, properties, ct)
                    .ConfigureAwait(false);

                    foreach (var header in content.Headers)
                    {
                        response.Headers.Add(header.Key, header.Value.ToArray());
                    }

                    await content.CopyToAsync(response.Body).ConfigureAwait(false);
                }
            }
            finally
            {
                foreach (var streamView in views)
                {
                    streamView.Dispose();
                }
            }
        }
Exemple #2
0
        public override async Task ExecuteResultAsync(IWebDavResponse response, CancellationToken ct)
        {
            await base.ExecuteResultAsync(response, ct);

            response.Headers["Accept-Ranges"] = new[] { "bytes" };

            var properties = await _document.GetProperties(response.Dispatcher).ToList(ct);

            var etagProperty = properties.OfType <GetETagProperty>().FirstOrDefault();

            if (etagProperty != null)
            {
                var propValue = await etagProperty.GetValueAsync(ct);

                response.Headers["ETag"] = new[] { propValue.ToString() };
            }

            if (!_returnFile)
            {
                var lastModifiedProp = properties.OfType <LastModifiedProperty>().FirstOrDefault();
                if (lastModifiedProp != null)
                {
                    var propValue = await lastModifiedProp.GetValueAsync(ct);

                    response.Headers["Last-Modified"] = new[] { propValue.ToString("R") };
                }

                return;
            }

            var views = new List <StreamView>();

            try
            {
                foreach (var rangeItem in _rangeItems)
                {
                    var baseStream = await _document.OpenReadAsync(ct);

                    var streamView = await StreamView
                                     .CreateAsync(baseStream, rangeItem.From, rangeItem.Length, ct)
                    ;

                    views.Add(streamView);
                }

                string contentType;
                var    contentTypeProp = properties.OfType <GetContentTypeProperty>().FirstOrDefault();
                if (contentTypeProp != null)
                {
                    contentType = await contentTypeProp.GetValueAsync(ct);
                }
                else
                {
                    contentType = MimeTypesMap.DefaultMimeType;
                }

                if (_rangeItems.Count == 1)
                {
                    // No multipart content
                    var rangeItem  = _rangeItems.Single();
                    var streamView = views.Single();
                    using (var streamContent = new StreamContent(streamView))
                    {
                        streamContent.Headers.ContentRange = new ContentRangeHeaderValue(
                            rangeItem.From,
                            rangeItem.To,
                            _document.Length);
                        streamContent.Headers.ContentLength = rangeItem.Length;

                        streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType);

                        await SetPropertiesToContentHeaderAsync(streamContent, properties, ct)
                        ;

                        foreach (var header in streamContent.Headers)
                        {
                            response.Headers.Add(header.Key, header.Value.ToArray());
                        }

                        // Use the CopyToAsync function of the stream itself, because
                        // we're able to pass the cancellation token. This is a workaround
                        // for issue dotnet/corefx#9071 and fixes FubarDevelopment/WebDavServer#47.
                        await streamView.CopyToAsync(response.Body, 81920, ct)
                        ;
                    }
                }
                else
                {
                    // Multipart content
                    using (var multipart = new MultipartContent("byteranges"))
                    {
                        var index = 0;
                        foreach (var rangeItem in _rangeItems)
                        {
                            var streamView  = views[index++];
                            var partContent = new StreamContent(streamView);
                            partContent.Headers.ContentRange = new ContentRangeHeaderValue(
                                rangeItem.From,
                                rangeItem.To,
                                _document.Length);
                            partContent.Headers.ContentType   = MediaTypeHeaderValue.Parse(contentType);
                            partContent.Headers.ContentLength = rangeItem.Length;
                            multipart.Add(partContent);
                        }

                        await SetPropertiesToContentHeaderAsync(multipart, properties, ct)
                        ;

                        foreach (var header in multipart.Headers)
                        {
                            response.Headers.Add(header.Key, header.Value.ToArray());
                        }

                        // TODO: Workaround for issue dotnet/corefx#9071
                        await multipart.CopyToAsync(response.Body);
                    }
                }
            }
            finally
            {
                foreach (var streamView in views)
                {
                    streamView.Dispose();
                }
            }
        }