readonly Stream content;
readonly int bufferSize;
readonly CancellationToken cancellationToken;
+ readonly long startPosition;
+ bool contentCopied;
public StreamContent (Stream content)
: this (content, 16 * 1024)
this.content = content;
this.bufferSize = bufferSize;
+
+ if (content.CanSeek) {
+ startPosition = content.Position;
+ }
}
//
protected internal override Task SerializeToStreamAsync (Stream stream, TransportContext context)
{
+ if (contentCopied) {
+ if (!content.CanSeek) {
+ throw new InvalidOperationException ("The stream was already consumed. It cannot be read again.");
+ }
+
+ content.Seek (startPosition, SeekOrigin.Begin);
+ } else {
+ contentCopied = true;
+ }
+
return content.CopyToAsync (stream, bufferSize, cancellationToken);
}
length = 0;
return false;
}
- length = content.Length;
+ length = content.Length - startPosition;
return true;
}
}
/*
sc = new StreamContent (new ExceptionStream ());
try {
- sc.CopyToAsync (m).Wait ();
- Assert.Fail ("#2");
+ sc.CopyToAsync (m).Wait ();
+ Assert.Fail ("#2");
} catch (AggregateException) {
}
*/
Assert.IsTrue (hit, "#10");
}
+ [Test]
+ public void CopyToAsync_Twice ()
+ {
+ var ms = new MemoryStream();
+ ms.WriteByte(4);
+ ms.WriteByte(12);
+ ms.WriteByte(7);
+ ms.Seek(1, SeekOrigin.Begin);
+
+ var sc = new StreamContent(ms);
+
+ var dest = new MemoryStream();
+ var task = sc.CopyToAsync(dest);
+ Assert.True(task.Wait(3000), "#0");
+ Assert.AreEqual(2, dest.Length, "#1");
+ dest.Seek(0, SeekOrigin.Begin);
+ Assert.AreEqual(12, dest.ReadByte(), "#2");
+
+ dest = new MemoryStream();
+ task = sc.CopyToAsync(dest);
+ Assert.True(task.Wait(3000), "#10");
+ Assert.AreEqual(2, dest.Length, "#11");
+ dest.Seek(0, SeekOrigin.Begin);
+ Assert.AreEqual(12, dest.ReadByte(), "#12");
+ }
+
[Test]
public void CopyToAsync_ClosedInput ()
{