MultipartParser.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. using System.Text.RegularExpressions;
  5. /// <summary>
  6. /// MultipartParser http://multipartparser.codeplex.com
  7. /// Reads a multipart form data stream and returns the filename, content type and contents as a stream.
  8. /// 2009 Anthony Super http://antscode.blogspot.com
  9. /// fixed by: Samuray
  10. /// </summary>
  11. namespace FastReport.Service
  12. {
  13. public class MultipartParser
  14. {
  15. public MultipartParser(Stream stream)
  16. {
  17. this.Parse(stream, Encoding.UTF8);
  18. }
  19. public MultipartParser(Stream stream, Encoding encoding)
  20. {
  21. this.Parse(stream, encoding);
  22. }
  23. private void Parse(Stream stream, Encoding encoding)
  24. {
  25. this.Success = false;
  26. // Read the stream into a byte array
  27. byte[] data = ToByteArray(stream);
  28. // Copy to a string for header parsing
  29. string content = encoding.GetString(data);
  30. // The first line should contain the delimiter
  31. int delimiterEndIndex = content.IndexOf("\r\n");
  32. if (delimiterEndIndex > -1)
  33. {
  34. string delimiter = content.Substring(0, content.IndexOf("\r\n"));
  35. // Look for Content-Type
  36. //Regex re = new Regex(@"(?<=Content\-Type:)(.*?)(?=\r\n\r\n)");
  37. // fixed by Samuray
  38. Regex re = new Regex(@"(?<=Content\-Type:)(.*?)(?=\r\n)");
  39. Match contentTypeMatch = re.Match(content);
  40. //Content-Transfer-Encoding
  41. // Look for filename
  42. re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");
  43. Match filenameMatch = re.Match(content);
  44. // Did we find the required values?
  45. if (contentTypeMatch.Success && filenameMatch.Success)
  46. {
  47. // Set properties
  48. this.ContentType = contentTypeMatch.Value.Trim();
  49. this.Filename = filenameMatch.Value.Trim();
  50. // Get the start & end indexes of the file contents
  51. //int startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length;
  52. // fixed by Samuray
  53. int startIndex = content.IndexOf("\r\n\r\n") + "\r\n\r\n".Length;
  54. byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
  55. int endIndex = IndexOf(data, delimiterBytes, startIndex);
  56. int contentLength = endIndex - startIndex;
  57. // Extract the file contents from the byte array
  58. byte[] fileData = new byte[contentLength];
  59. Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
  60. this.FileContents = fileData;
  61. this.Success = true;
  62. }
  63. }
  64. }
  65. private int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex)
  66. {
  67. int index = 0;
  68. int startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);
  69. if (startPos != -1)
  70. {
  71. while ((startPos + index) < searchWithin.Length)
  72. {
  73. if (searchWithin[startPos + index] == serachFor[index])
  74. {
  75. index++;
  76. if (index == serachFor.Length)
  77. {
  78. return startPos;
  79. }
  80. }
  81. else
  82. {
  83. startPos = Array.IndexOf<byte>(searchWithin, serachFor[0], startPos + index);
  84. if (startPos == -1)
  85. {
  86. return -1;
  87. }
  88. index = 0;
  89. }
  90. }
  91. }
  92. return -1;
  93. }
  94. private byte[] ToByteArray(Stream stream)
  95. {
  96. byte[] buffer = new byte[32768];
  97. using (MemoryStream ms = new MemoryStream())
  98. {
  99. stream.CopyTo(ms);
  100. return ms.ToArray();
  101. }
  102. }
  103. public bool Success
  104. {
  105. get;
  106. private set;
  107. }
  108. public string ContentType
  109. {
  110. get;
  111. private set;
  112. }
  113. public string Filename
  114. {
  115. get;
  116. private set;
  117. }
  118. public byte[] FileContents
  119. {
  120. get;
  121. private set;
  122. }
  123. }
  124. }