HttpPostedFile.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. using System;
  2. using System.IO;
  3. public sealed class HttpPostedFile : IDisposable
  4. {
  5. private string _name;
  6. private string _contentType;
  7. private Stream _stream;
  8. private bool _disposed = false;
  9. internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length)
  10. {
  11. _name = name;
  12. _contentType = content_type;
  13. _stream = new ReadSubStream(base_stream, offset, length);
  14. }
  15. public string ContentType => _contentType;
  16. public int ContentLength => (int)_stream.Length;
  17. public string FileName => _name;
  18. public Stream InputStream => _stream;
  19. /// <summary>
  20. /// Releases the unmanaged resources and disposes of the managed resources used.
  21. /// </summary>
  22. public void Dispose()
  23. {
  24. if (_disposed)
  25. {
  26. return;
  27. }
  28. _stream.Dispose();
  29. _stream = null;
  30. _name = null;
  31. _contentType = null;
  32. _disposed = true;
  33. }
  34. private class ReadSubStream : Stream
  35. {
  36. private Stream _stream;
  37. private long _offset;
  38. private long _end;
  39. private long _position;
  40. public ReadSubStream(Stream s, long offset, long length)
  41. {
  42. _stream = s;
  43. _offset = offset;
  44. _end = offset + length;
  45. _position = offset;
  46. }
  47. public override bool CanRead => true;
  48. public override bool CanSeek => true;
  49. public override bool CanWrite => false;
  50. public override long Length => _end - _offset;
  51. public override long Position
  52. {
  53. get => _position - _offset;
  54. set
  55. {
  56. if (value > Length)
  57. {
  58. throw new ArgumentOutOfRangeException(nameof(value));
  59. }
  60. _position = Seek(value, SeekOrigin.Begin);
  61. }
  62. }
  63. public override void Flush()
  64. {
  65. }
  66. public override int Read(byte[] buffer, int dest_offset, int count)
  67. {
  68. if (buffer == null)
  69. {
  70. throw new ArgumentNullException(nameof(buffer));
  71. }
  72. if (dest_offset < 0)
  73. {
  74. throw new ArgumentOutOfRangeException(nameof(dest_offset), "< 0");
  75. }
  76. if (count < 0)
  77. {
  78. throw new ArgumentOutOfRangeException(nameof(count), "< 0");
  79. }
  80. int len = buffer.Length;
  81. if (dest_offset > len)
  82. {
  83. throw new ArgumentException("destination offset is beyond array size", nameof(dest_offset));
  84. }
  85. // reordered to avoid possible integer overflow
  86. if (dest_offset > len - count)
  87. {
  88. throw new ArgumentException("Reading would overrun buffer", nameof(count));
  89. }
  90. if (count > _end - _position)
  91. {
  92. count = (int)(_end - _position);
  93. }
  94. if (count <= 0)
  95. {
  96. return 0;
  97. }
  98. _stream.Position = _position;
  99. int result = _stream.Read(buffer, dest_offset, count);
  100. if (result > 0)
  101. {
  102. _position += result;
  103. }
  104. else
  105. {
  106. _position = _end;
  107. }
  108. return result;
  109. }
  110. public override int ReadByte()
  111. {
  112. if (_position >= _end)
  113. {
  114. return -1;
  115. }
  116. _stream.Position = _position;
  117. int result = _stream.ReadByte();
  118. if (result < 0)
  119. {
  120. _position = _end;
  121. }
  122. else
  123. {
  124. _position++;
  125. }
  126. return result;
  127. }
  128. public override long Seek(long d, SeekOrigin origin)
  129. {
  130. long real;
  131. switch (origin)
  132. {
  133. case SeekOrigin.Begin:
  134. real = _offset + d;
  135. break;
  136. case SeekOrigin.End:
  137. real = _end + d;
  138. break;
  139. case SeekOrigin.Current:
  140. real = _position + d;
  141. break;
  142. default:
  143. throw new ArgumentException("Unknown SeekOrigin value", nameof(origin));
  144. }
  145. long virt = real - _offset;
  146. if (virt < 0 || virt > Length)
  147. {
  148. throw new ArgumentException("Invalid position", nameof(d));
  149. }
  150. _position = _stream.Seek(real, SeekOrigin.Begin);
  151. return _position;
  152. }
  153. public override void SetLength(long value)
  154. {
  155. throw new NotSupportedException();
  156. }
  157. public override void Write(byte[] buffer, int offset, int count)
  158. {
  159. throw new NotSupportedException();
  160. }
  161. }
  162. }