Exemple #1
0
        public void NoOverlappingRangesThrowException(
            string ranges,
            int innerStreamLength,
            string contentRange
            )
        {
            // Arrange
            string data = new String('a', innerStreamLength);

            byte[]           bytes     = Encoding.UTF8.GetBytes(data);
            MemoryStream     memStream = new MemoryStream(bytes);
            RangeHeaderValue range     = RangeHeaderValue.Parse(ranges);

            // Act
            try
            {
                new ByteRangeStreamContent(memStream, range, _expectedMediatype);
            }
            catch (InvalidByteRangeException invalidByteRangeException)
            {
                ContentRangeHeaderValue expectedContentRange = ContentRangeHeaderValue.Parse(
                    contentRange
                    );
                Assert.Equal(expectedContentRange, invalidByteRangeException.ContentRange);
            }
        }
Exemple #2
0
        public void SingleRangeGeneratesNonMultipartContent(
            string ranges,
            int innerStreamLength,
            string contentRange
            )
        {
            // Arrange
            string data = new String('a', innerStreamLength);

            byte[]           bytes     = Encoding.UTF8.GetBytes(data);
            MemoryStream     memStream = new MemoryStream(bytes);
            RangeHeaderValue range     = RangeHeaderValue.Parse(ranges);

            // Act
            ByteRangeStreamContent rangeContent = new ByteRangeStreamContent(
                memStream,
                range,
                _expectedMediatype
                );

            // Assert
            Assert.Equal(_expectedMediatype, rangeContent.Headers.ContentType);
            ContentRangeHeaderValue expectedContentRange = ContentRangeHeaderValue.Parse(
                contentRange
                );

            Assert.Equal(expectedContentRange, rangeContent.Headers.ContentRange);
        }
Exemple #3
0
        public void Parse()
        {
            var res = ContentRangeHeaderValue.Parse("bytes  0 - 499/ 9223372036854775807");

            Assert.AreEqual(0, res.From, "#1");
            Assert.AreEqual(499, res.To, "#2");
            Assert.AreEqual(9223372036854775807, res.Length, "#3");
            Assert.AreEqual("bytes 0-499/9223372036854775807", res.ToString(), "#4");

            res = ContentRangeHeaderValue.Parse("bytes  */ 8");
            Assert.IsNull(res.From, "#11");
            Assert.IsNull(res.To, "#12");
            Assert.AreEqual(8, res.Length, "#13");
            Assert.AreEqual("bytes */8", res.ToString(), "#14");

            res = ContentRangeHeaderValue.Parse("by  */*");
            Assert.IsNull(res.From, "#21");
            Assert.IsNull(res.To, "#22");
            Assert.IsNull(res.Length, "#23");
            Assert.AreEqual("by */*", res.ToString(), "#24");

            res = ContentRangeHeaderValue.Parse("bytes  199999999999999999 - 999999999999999999/ 9223372036854775807");
            Assert.AreEqual(199999999999999999, res.From, "#31");
            Assert.AreEqual(999999999999999999, res.To, "#32");
            Assert.AreEqual(9223372036854775807, res.Length, "#33");
            Assert.AreEqual("bytes 199999999999999999-999999999999999999/9223372036854775807", res.ToString(), "#34");
        }
        public async Task <string> PutChunk(
            string id,
            string uploadKey,
            string chunkKey,
            string sequentialState,
            int chunkIndex,
            int totalChunks,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Logger.LogDebug($"SequentialState: {sequentialState}");

            var  range  = ContentRangeHeaderValue.Parse(Request.Headers["X-Content-Range"]);
            long length = (long)range.To - (long)range.From + 1;

            using (var requestStream = new StreamRequestWrapper(Request.Body, length))
                return(await backend.ChunkedUploadChunkAsync(
                           context,
                           id,
                           uploadKey,
                           chunkKey,
                           chunkIndex,
                           totalChunks,
                           sequentialState,
                           (long)range.From,
                           (long)range.To,
                           (long)range.Length,
                           requestStream,
                           cancellationToken
                           ));
        }
Exemple #5
0
        public async Task <UploadContextModel> PatchRange(
            UploadContextModel uploadContext,
            int chunkIndex,
            CancellationToken cancellationToken = default(CancellationToken)
            )
        {
            if (Request.Headers["Content-Range"].Count == 0)
            {
                throw new Exception("Missing required Content-Range header");
            }
            var range = ContentRangeHeaderValue.Parse(Request.Headers["Content-Range"].ToString());

            if (range.From == null)
            {
                throw new ArgumentNullException("Range Header From must be specified");
            }
            if (range.To == null)
            {
                throw new ArgumentNullException("Range Header To must be specified");
            }
            if ((long)range.Length != uploadContext.FileLength)
            {
                throw new ArgumentNullException("Range Header Length does not match UploadContext.FileLength");
            }


            return(await FileContentsService.UploadChunkAsync(
                       uploadContext, (long)range.From, (long)range.To, Request.Body, chunkIndex, cancellationToken));
        }
Exemple #6
0
        /// <summary>
        /// Copies content headers.
        /// </summary>
        /// <param name="httpRequest">Outgoing request.</param>
        /// <param name="headerMap">Incoming request header map.</param>
        public static void CopyContentHeaders(this HttpRequestMessage httpRequest, Dictionary <string, string> headerMap)
        {
            httpRequest.Content.Headers.ContentDisposition =
                headerMap.ContainsKey("Content-Disposition") ?
                ContentDispositionHeaderValue.Parse(headerMap["Content-Disposition"]) :
                httpRequest.Content.Headers.ContentDisposition;

            httpRequest.Content.Headers.ContentLocation =
                headerMap.ContainsKey("Content-Location") ?
                new Uri(headerMap["Content-Location"]) :
                httpRequest.Content.Headers.ContentLocation;

            httpRequest.Content.Headers.ContentRange =
                headerMap.ContainsKey("Content-Range") ?
                ContentRangeHeaderValue.Parse(headerMap["Content-Range"]) :
                httpRequest.Content.Headers.ContentRange;

            httpRequest.Content.Headers.ContentType =
                headerMap.ContainsKey("Content-Type") ?
                MediaTypeHeaderValue.Parse(headerMap["Content-Type"]) :
                httpRequest.Content.Headers.ContentType;

            httpRequest.Content.Headers.Expires =
                headerMap.ContainsKey("Expires") ?
                DateTimeOffset.Parse(headerMap["Expires"]) :
                httpRequest.Content.Headers.Expires;

            httpRequest.Content.Headers.LastModified =
                headerMap.ContainsKey("Last-Modified") ?
                DateTimeOffset.Parse(headerMap["Last-Modified"]) :
                httpRequest.Content.Headers.LastModified;
        }
        public async Task <HttpResponse> Send(Uri requestUri, HttpMethod method, RequestParameters requestParams, CancellationToken cancellationToken)
        {
            using (var request = new HttpRequestMessage(method, requestUri))
            {
                if (requestParams.Content != null)
                {
                    request.Content = requestParams.Content;
                    if (!string.IsNullOrEmpty(requestParams.ContentType))
                    {
                        request.Content.Headers.ContentType = new MediaTypeHeaderValue(requestParams.ContentType);
                    }
                }

                foreach (var header in requestParams.Headers)
                {
                    // When setting Content-Range as a Header on the HTTPRequestHeader directly, the call to SendAsync crashes out with the following exception:
                    // "Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects."
                    if (header.Key.Equals("Content-Range"))
                    {
                        request.Content.Headers.ContentRange = ContentRangeHeaderValue.Parse(header.Value);
                    }
                    else
                    {
                        request.Headers.Add(header.Key, header.Value);
                    }
                }

                var response = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);

                return(new HttpResponse(response.Content, (int)response.StatusCode, response.ReasonPhrase));
            }
        }
        public void Parse_Invalid()
        {
            try {
                ContentRangeHeaderValue.Parse(null);
                Assert.Fail("#1");
            } catch (FormatException) {
            }

            try {
                ContentRangeHeaderValue.Parse("  ");
                Assert.Fail("#2");
            } catch (FormatException) {
            }

            try {
                ContentRangeHeaderValue.Parse("a b");
                Assert.Fail("#3");
            } catch (FormatException) {
            }

            try {
                ContentRangeHeaderValue.Parse("bytes 10/");
                Assert.Fail("#4");
            } catch (FormatException) {
            }
        }
        public void MultipleRangesGeneratesMultipartByteRangesContent(string ranges, int innerStreamLength, int expectedBodyparts, string[] contentRanges)
        {
            // Arrange
            string data = new String('a', innerStreamLength);

            byte[]           bytes     = Encoding.UTF8.GetBytes(data);
            MemoryStream     memStream = new MemoryStream(bytes);
            RangeHeaderValue range     = RangeHeaderValue.Parse(ranges);

            // Act
            ByteRangeStreamContent content = new ByteRangeStreamContent(memStream, range, _expectedMediatype);
            MemoryStream           result  = new MemoryStream();

            content.CopyToAsync(result).Wait();
            MultipartMemoryStreamProvider multipart = content.ReadAsMultipartAsync().Result;

            // Assert
            Assert.Equal(expectedBodyparts, multipart.Contents.Count);
            for (int count = 0; count < multipart.Contents.Count; count++)
            {
                MediaTypeHeaderValue contentType = multipart.Contents[count].Headers.ContentType;
                Assert.Equal(_expectedMediatype, contentType);

                ContentRangeHeaderValue expectedContentRange = ContentRangeHeaderValue.Parse(contentRanges[count]);
                ContentRangeHeaderValue contentRange         = multipart.Contents[count].Headers.ContentRange;
                Assert.Equal(expectedContentRange, contentRange);
            }
        }
Exemple #10
0
    public void Parse_SetOfValidValueStrings_ParsedCorrectly()
    {
        CheckValidParse(" bytes 1-2/3 ", new ContentRangeHeaderValue(1, 2, 3));
        CheckValidParse("bytes  *  /  3", new ContentRangeHeaderValue(3));

        CheckValidParse(" custom 1234567890123456789-1234567890123456799/*",
                        new ContentRangeHeaderValue(1234567890123456789, 1234567890123456799)
        {
            Unit = "custom"
        });

        CheckValidParse(" custom * / 123 ",
                        new ContentRangeHeaderValue(123)
        {
            Unit = "custom"
        });

        // Note that we don't have a public constructor for value 'bytes */*' since the RFC doesn't mention a
        // scenario for it. However, if a server returns this value, we're flexible and accept it.
        var result = ContentRangeHeaderValue.Parse("bytes */*");

        Assert.Equal("bytes", result.Unit);
        Assert.Null(result.From);
        Assert.Null(result.To);
        Assert.Null(result.Length);
        Assert.False(result.HasRange, "HasRange");
        Assert.False(result.HasLength, "HasLength");
    }
Exemple #11
0
        public void GetRawHeaders_ReturnsExpectedHeaders()
        {
            // No headers
            HttpRequestMessage request = new HttpRequestMessage();
            var headers = request.GetRawHeaders();

            Assert.Equal(0, headers.Count);

            // One header
            request = new HttpRequestMessage();
            string testHeader1 = "TestValue";

            request.Headers.Add("Header1", testHeader1);
            headers = request.GetRawHeaders();
            Assert.Equal(1, headers.Count);
            Assert.Equal(testHeader1, headers["Header1"]);

            // Multiple headers
            string userAgent   = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36";
            string accept      = "text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8";
            string testHeader2 = "foo,bar,baz";
            string testHeader3 = "foo bar baz";
            string testHeader4 = "testValue4";

            request.Headers.Add("User-Agent", userAgent);
            request.Headers.Add("Accept", accept);
            request.Headers.Add("Header2", testHeader2);
            request.Headers.Add("Header3", testHeader3);
            request.Headers.Add("Header4", testHeader4);
            request.Headers.Add("Empty", string.Empty);
            var str = request.Headers.ToString();

            headers = request.GetRawHeaders();
            Assert.Equal(7, headers.Count);
            Assert.Equal(userAgent, headers["User-Agent"]);
            Assert.Equal(accept, headers["Accept"]);
            Assert.Equal(testHeader1, headers["Header1"]);
            Assert.Equal(testHeader2, headers["Header2"]);
            Assert.Equal(testHeader3, headers["Header3"]);
            Assert.Equal(testHeader4, headers["Header4"]);
            Assert.Equal(testHeader4, headers["header4"]);
            Assert.Equal(string.Empty, headers["Empty"]);

            // Content headers
            request.Content = new StringContent("test");
            request.Content.Headers.ContentType        = new MediaTypeHeaderValue("text/html");
            request.Content.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse("form-data; name=\"fieldName\"; filename=\"filename.jpg\"");
            request.Content.Headers.ContentRange       = ContentRangeHeaderValue.Parse("bytes 200-1000/67589");
            headers = request.GetRawHeaders();
            Assert.Equal(10, headers.Count);
            Assert.Equal("text/html", headers["Content-Type"]);
            Assert.Equal("form-data; name=\"fieldName\"; filename=\"filename.jpg\"", headers["Content-Disposition"]);
            Assert.Equal("bytes 200-1000/67589", headers["Content-Range"]);
        }
Exemple #12
0
 private async Task <Tuple <File, ContentRangeHeaderValue> > ProcessResumableUploadResponse(HttpResponseMessage response)
 {
     if (response.IsSuccessStatusCode)
     {
         return(new Tuple <File, ContentRangeHeaderValue>(await response.Content.ReadJsonAsync <File>(), null));
     }
     if ((int)response.StatusCode == 308)
     {
         var range = response.Headers.GetValues("Range").First();
         var r     = ContentRangeHeaderValue.Parse("bytes " + range.Substring(6) + "/*");
         return(new Tuple <File, ContentRangeHeaderValue>(null, r));
     }
     else
     {
         throw await ProcessException(response);
     }
 }
Exemple #13
0
        public async Task TestResponseContentHeaders()
        {
            var mock = new MockHttpClient();

            var currentDate       = DateTime.UtcNow;
            var expectedExpires   = new DateTimeOffset(currentDate.AddSeconds(60));
            var expectedByteArray = new byte[] { 65 };

            var expected = new ByteArrayContent(expectedByteArray);

            expected.Headers.Allow.Add("GET");
            expected.Headers.Allow.Add("POST");
            expected.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse("attachment");
            expected.Headers.ContentLength      = expectedByteArray.Length;
            expected.Headers.ContentLocation    = new Uri("https://example.com");
            expected.Headers.ContentRange       = ContentRangeHeaderValue.Parse("bytes 200-1000/67589");
            expected.Headers.ContentType        = MediaTypeHeaderValue.Parse("text/plain");
            expected.Headers.ContentMD5         = new byte[] { 1 };
            expected.Headers.ContentLanguage.Add("en-US");
            expected.Headers.ContentEncoding.Add("gzip");
            expected.Headers.Expires      = expectedExpires;
            expected.Headers.LastModified = currentDate;

            mock.SetupGet("/").ReturnsAsync(content: expected);

            var result = await mock.Object.GetAsync("/");

            var resultByteArray = await result.Content.ReadAsByteArrayAsync();

            Assert.Equal(expectedByteArray, resultByteArray);
            Assert.Equal("GET, POST", result.Content.Headers.Allow.ToString());
            Assert.Equal("attachment", result.Content.Headers.ContentDisposition.ToString());
            Assert.Equal(expectedByteArray.Length, result.Content.Headers.ContentLength);
            Assert.Equal("https://example.com/", result.Content.Headers.ContentLocation.AbsoluteUri);
            Assert.Equal("bytes 200-1000/67589", result.Content.Headers.ContentRange.ToString());
            Assert.Equal("text/plain", result.Content.Headers.ContentType.ToString());
            Assert.Equal(new byte[] { 1 }, result.Content.Headers.ContentMD5);
            Assert.Equal("en-US", result.Content.Headers.ContentLanguage.ToString());
            Assert.Equal("gzip", result.Content.Headers.ContentEncoding.ToString());
            Assert.NotNull(result.Content.Headers.Expires);
            Assert.NotNull(result.Content.Headers.LastModified);
            Assert.Equal(expectedExpires.ToString("s"), result.Content.Headers.Expires.Value.ToString("s"));
            Assert.Equal(currentDate.ToString("s"), result.Content.Headers.LastModified.Value.ToString("s"));
        }
        public void Parse()
        {
            var res = ContentRangeHeaderValue.Parse("bytes  0 - 499/ 1234");

            Assert.AreEqual(0, res.From, "#1");
            Assert.AreEqual(499, res.To, "#2");
            Assert.AreEqual(1234, res.Length, "#3");
            Assert.AreEqual("bytes 0-499/1234", res.ToString(), "#4");

            res = ContentRangeHeaderValue.Parse("bytes  */ 8");
            Assert.IsNull(res.From, "#11");
            Assert.IsNull(res.To, "#12");
            Assert.AreEqual(8, res.Length, "#13");
            Assert.AreEqual("bytes */8", res.ToString(), "#14");

            res = ContentRangeHeaderValue.Parse("by  */*");
            Assert.IsNull(res.From, "#21");
            Assert.IsNull(res.To, "#22");
            Assert.IsNull(res.Length, "#23");
            Assert.AreEqual("by */*", res.ToString(), "#24");
        }
Exemple #15
0
        /// <summary>
        /// Copies content headers.
        /// </summary>
        /// <param name="httpContent">Http content.</param>
        /// <param name="headerCollection">Header collection.</param>
        private static void CopyContentHeader(HttpContent httpContent, WebHeaderCollection headerCollection)
        {
            if (headerCollection["Content-Disposition"] != null)
            {
                httpContent.Headers.ContentDisposition = ContentDispositionHeaderValue.Parse(headerCollection["Content-Disposition"]);
            }

            if (headerCollection[HttpRequestHeader.ContentLocation] != null)
            {
                httpContent.Headers.ContentLocation = new Uri(headerCollection[HttpRequestHeader.ContentLocation]);
            }

            if (headerCollection[HttpRequestHeader.ContentRange] != null)
            {
                httpContent.Headers.ContentRange = ContentRangeHeaderValue.Parse(headerCollection[HttpRequestHeader.ContentRange]);
            }

            if (headerCollection[HttpRequestHeader.ContentType] != null)
            {
                httpContent.Headers.ContentType = MediaTypeHeaderValue.Parse(headerCollection[HttpRequestHeader.ContentType]);
            }

            if (headerCollection[HttpRequestHeader.Expires] != null)
            {
                httpContent.Headers.Expires = DateTimeOffset.Parse(headerCollection[HttpRequestHeader.Expires], CultureInfo.InvariantCulture);
            }

            if (headerCollection[HttpRequestHeader.LastModified] != null)
            {
                httpContent.Headers.LastModified = DateTimeOffset.Parse(headerCollection[HttpRequestHeader.LastModified], CultureInfo.InvariantCulture);
            }

            if (headerCollection[HttpRequestHeader.ContentLength] != null)
            {
                httpContent.Headers.ContentLength = long.Parse(headerCollection[HttpRequestHeader.ContentLength], CultureInfo.InvariantCulture);
            }
        }
Exemple #16
0
        /// <summary>
        /// Perform the WebDAV call and fire the callback when finished.
        /// </summary>
        /// <param name="uri"></param>
        /// <param name="headers"></param>
        /// <param name="method"></param>
        /// <param name="content"></param>
        private async Task <HttpResponseMessage> HttpUploadRequest(Uri uri, HttpMethod method, Stream content, IDictionary <string, string> headers = null, long?startbytes = null, long?endbytes = null, long?totalLength = null)
        {
            using (var request = new HttpRequestMessage(method, uri))
            {
                request.Headers.Connection.Add("Keep-Alive");
                if (!string.IsNullOrWhiteSpace(UserAgent))
                {
                    request.Headers.UserAgent.Add(new ProductInfoHeaderValue(UserAgent, UserAgentVersion));
                }
                else
                {
                    request.Headers.UserAgent.Add(new ProductInfoHeaderValue("WebDAVClient", AssemblyVersion));
                }

                if (headers != null)
                {
                    foreach (string key in headers.Keys)
                    {
                        request.Headers.Add(key, headers[key]);
                    }
                }

                // Need to send along content?
                if (content != null)
                {
                    request.Content = new StreamContent(content);
                    if (startbytes.HasValue && endbytes.HasValue)
                    {
                        var len = totalLength.HasValue ? totalLength.ToString() : "*";
                        request.Content.Headers.ContentRange  = ContentRangeHeaderValue.Parse($"bytes {startbytes}-{endbytes}/{len}");
                        request.Content.Headers.ContentLength = endbytes - startbytes + 1;
                    }
                }

                return(await _httpClientWrapper.SendUploadAsync(request).ConfigureAwait(false));
            }
        }
Exemple #17
0
 /// <summary>
 /// Returns ContentRange from headers.
 /// </summary>
 /// <param name="headers">Headers collection</param>
 /// <returns>ContentRange object</returns>
 public static ContentRangeHeaderValue GetContentRange(this WebHeaderCollection headers)
 {
     Contract.Requires(headers != null);
     return(ContentRangeHeaderValue.Parse(headers["Content-Range"]));
 }
 private void CheckInvalidParse(string input)
 {
     Assert.Throws <FormatException>(() => { ContentRangeHeaderValue.Parse(input); });
 }
        private void CheckValidParse(string input, ContentRangeHeaderValue expectedResult)
        {
            ContentRangeHeaderValue result = ContentRangeHeaderValue.Parse(input);

            Assert.Equal(expectedResult, result);
        }
Exemple #20
0
        public async Task <ActionResult> UploadChunk(
            PathIdentifier pathIdentifier,
            BrowserFileInformation fileInformation,
            string token,
            CancellationToken cancellationToken = default(CancellationToken)
            )
        {
            if (!Request.ContentLength.HasValue)
            {
                throw new Exception("Missing Content-Length header");
            }
            if (Request.Headers["Content-Range"].Count == 0)
            {
                throw new Exception("Missing Content-Range header");
            }
            if (Request.Headers["Content-Disposition"].Count == 0)
            {
                throw new Exception("Missing Content-Disposition header");
            }

            var range = ContentRangeHeaderValue.Parse(Request.Headers["Content-Range"]);

            if (!range.HasLength)
            {
                throw new Exception("Content-Range header does not include total length");
            }

            long from       = (long)range.From;
            long to         = (long)range.To;
            long fileLength = (long)range.Length;

            var fileName = fileInformation?.Name;

            if (fileName == null)
            {
                var contentDisposition = ContentDispositionHeaderValue.Parse(Request.Headers["Content-Disposition"]);
                fileName = contentDisposition?.FileName;
                if (fileName == null)
                {
                    throw new Exception("Filename is not specified in either Content-Disposition header or fileInformation");
                }

                // for some dumb reason, the ContentDispositionHeaderValue parser doesn't finish parsing file names
                // it leaves them quoted
                if (fileName.StartsWith('"') && fileName.EndsWith('"') && fileName.Length > 1)
                {
                    fileName = WebUtility.UrlDecode(fileName.Substring(1, fileName.Length - 2));
                }
            }

            Stream             stream     = Request.Body;
            UploadContextModel tokenState = null;

            // test retries
            //if ((new Random()).NextDouble() < .3)
            //    throw new Exception("Chaos Monkey");

            bool isFirstChunk = from == 0;
            bool isLastChunk  = to == (fileLength - 1);

            FileIdentifier fileIdentifier = null;

            var folderModel = await Connection.Folder.GetOrThrowAsync(pathIdentifier);

            var modules = ModuleConfigurator.GetActiveModules(folderModel);

            // === Step 1: Begin Upload
            if (isFirstChunk)
            {
                var fileModel = new FileModel
                {
                    Identifier = new FileIdentifier(pathIdentifier, null),
                    Name       = fileName,
                    Modified   = fileInformation?.LastModified != null
                        ? epoch.AddMilliseconds(fileInformation.LastModified.Value)
                        : DateTime.UtcNow,
                    Length   = fileLength,
                    MimeType = fileInformation?.Type ?? Request.ContentType ?? "application/octet-stream",
                }.InitializeEmptyMetadata();

                fileModel.Created = new DateTime(Math.Min(DateTime.UtcNow.Ticks, fileModel.Modified.Ticks), DateTimeKind.Utc);

                // some browsers will send us the relative path of a file during a folder upload
                var relativePath = fileInformation?.FullPath;
                if (!string.IsNullOrWhiteSpace(relativePath) && relativePath != "/")
                {
                    if (relativePath.StartsWith("/"))
                    {
                        relativePath = relativePath.Substring(1);
                    }

                    pathIdentifier = pathIdentifier.CreateChild(relativePath);
                }

                fileModel.MetaPathIdentifierWrite(pathIdentifier);

                foreach (var module in modules)
                {
                    await module.PreUploadAsync(folderModel, fileModel);
                }

                tokenState = await Connection.File.UploadBeginAsync(fileModel, cancellationToken : cancellationToken);
            }
            else
            {
                if (token == null)
                {
                    throw new Exception("Uploaded secondary chunk without token");
                }

                tokenState = JsonConvert.DeserializeObject <UploadContextModel>(token);
            }


            // === Step 2: Send this Chunk
            using (stream)
            {
                if (!isLastChunk)
                {
                    if (to - from != tokenState.ChunkSize - 1)
                    {
                        throw new Exception($"Chunk Size Mismatch: received ({to - from}) expected ({tokenState.ChunkSize})");
                    }
                }

                int chunkIndex = (int)(from / tokenState.ChunkSize);

                tokenState = await Connection.File.UploadSendChunkAsync(
                    tokenState,
                    chunkIndex,
                    from,
                    to,
                    stream,
                    cancellationToken : cancellationToken
                    );
            }

            // === Step 3: End the Upload
            if (isLastChunk)  // if file is one chunk, all three steps happen in a single call
            {
                var fileModel = await Connection.File.UploadEndAsync(tokenState, cancellationToken : cancellationToken);

                fileIdentifier = fileModel.Identifier;

                foreach (var module in modules)
                {
                    await module.PostUploadAsync(folderModel, fileModel);
                }
            }

            return(Json(new APIResponse <UploadedFileResponse>
            {
                Response = new UploadedFileResponse
                {
                    FileIdentifier = fileIdentifier,
                    Token = JsonConvert.SerializeObject(tokenState)
                }
            }));
        }
 /// <summary>
 /// Returns ContentRange from headers.
 /// </summary>
 /// <param name="headers">Headers collection</param>
 /// <returns>ContentRange object</returns>
 public static ContentRangeHeaderValue GetContentRange(this WebHeaderCollection headers)
 {
     return(ContentRangeHeaderValue.Parse(headers["Content-Range"]));
 }
Exemple #22
0
 public void Parse_SetOfInvalidValueStrings_Throws(string?input)
 {
     Assert.Throws <FormatException>(() => ContentRangeHeaderValue.Parse(input));
 }
        /// <summary>
        /// Insert a content HTTP header
        /// </summary>
        /// <param name="header">A <see cref="System.Net.Http.Headers.HttpContentHeaders"/> object on wich the content header will be recorded.</param>
        /// <param name="name">The header attribute name.</param>
        /// <param name="value">The header attribute value.</param>
        public void AddContentHeader(HttpContentHeaders header, string name, string value)
        {
            if (name.Equals("Allow", StringComparison.OrdinalIgnoreCase))
            {
                header.Add("Allow", value);
            }

            else if (name.Equals("Content-Disposition", StringComparison.OrdinalIgnoreCase))
            {
                header.ContentDisposition = new ContentDispositionHeaderValue(value);
            }

            else if (name.Equals("Content-Encoding", StringComparison.OrdinalIgnoreCase))
            {
                header.Add("Content-Encoding", value);
            }

            else if (name.Equals("Content-Language", StringComparison.OrdinalIgnoreCase))
            {
                header.Add("Content-Language", value);
            }

            else if (name.Equals("Content-Length", StringComparison.OrdinalIgnoreCase))
            {
                header.ContentLength = long.Parse(value);
            }

            else if (name.Equals("Content-Length", StringComparison.OrdinalIgnoreCase))
            {
                header.ContentLength = long.Parse(value);
            }

            else if (name.Equals("Content-Location", StringComparison.OrdinalIgnoreCase))
            {
                header.ContentLocation = new Uri(value);
            }

            else if (name.Equals("Content-MD5", StringComparison.OrdinalIgnoreCase))
            {
                header.ContentMD5 = Encoding.ASCII.GetBytes(value);
            }

            else if (name.Equals("Content-Range", StringComparison.OrdinalIgnoreCase))
            {
                header.ContentRange = ContentRangeHeaderValue.Parse(value);
            }

            else if (name.Equals("Content-Type", StringComparison.OrdinalIgnoreCase))
            {
                header.Add("Content-Type", value);
            }

//				C# does not allow any value here... Don't know why
//				header.ContentType = new MediaTypeHeaderValue(value);

            else if (name.Equals("Expires", StringComparison.OrdinalIgnoreCase))
            {
                header.Expires = DateTimeOffset.Parse(value);
            }

            else if (name.Equals("Last-Modified", StringComparison.OrdinalIgnoreCase))
            {
                header.LastModified = DateTimeOffset.Parse(value);
            }

            else
            {
                throw new ArgumentException("Content has no attribute named: " + name);
            }
        }