他のソリューションがバイナリ ファイルで抱えていた問題は、応答を文字列に変換して解析し、その文字列をファイルに変換し直すことでした。これはバイナリ データでは機能しません。応答を文字列に変換して解析する代わりに、それを byte[] のままにして、ここにあるコードを使用して区切り文字で byte[] として分割するという解決策を思いつきました。それが完了したら、各ピースを文字列に変換して、それがパラメーターかファイルかを確認し、パラメーターの場合は読み取り、そうでない場合はファイルとして書き込みます。これは、Stream が byte[] で、区切り文字が文字列であることを前提とした作業コードです。
// given byte[] streamByte, String delimiterString, and Encoding encoding
Regex regQuery;
Match regMatch;
string propertyType;
byte[] delimiterBytes = encoding.GetBytes(delimiterString);
byte[] delimiterWithNewLineBytes = encoding.GetBytes(delimiterString + "\r\n");
// the request ends DELIMITER--\r\n
byte[] delimiterEndBytes = encoding.GetBytes("\r\n" + delimiterString + "--\r\n");
int lengthDifferenceWithEndBytes = (delimiterString + "--\r\n").Length;
// seperate by delimiter + newline
// ByteArraySplit code found at https://stackoverflow.com/a/9755250/4244411
byte[][] separatedStream = ByteArraySplit(streamBytes, delimiterWithNewLineBytes);
streamBytes = null;
for (int i = 0; i < separatedStream.Length; i++)
{
// parse out whether this is a parameter or a file
// get the first line of the byte[] as a string
string thisPieceAsString = encoding.GetString(separatedStream[i]);
if (string.IsNullOrWhiteSpace(thisPieceAsString)) { continue; }
string firstLine = thisPieceAsString.Substring(0, thisPieceAsString.IndexOf("\r\n"));
// Check the item to see what it is
regQuery = new Regex(@"(?<=name\=\"")(.*?)(?=\"")");
regMatch = regQuery.Match(firstLine);
propertyType = regMatch.Value.Trim();
// get the index of the start of the content and the end of the content
int indexOfStartOfContent = thisPieceAsString.IndexOf("\r\n\r\n") + "\r\n\r\n".Length;
// this line compares the name to the name of the html input control,
// this can be smarter by instead looking for the filename property
if (propertyType != "files")
{
// this is a parameter!
// if this is the last piece, chop off the final delimiter
int lengthToRemove = (i == separatedStream.Length - 1) ? lengthDifferenceWithEndBytes : 0;
string value = thisPieceAsString.Substring(indexOfStartOfContent, thisPieceAsString.Length - "\r\n".Length - indexOfStartOfContent - lengthToRemove);
// do something with the parameter
}
else
{
// this is a file!
regQuery = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")");
regMatch = regQuery.Match(firstLine);
string fileName = regMatch.Value.Trim();
// get the content byte[]
// if this is the last piece, chop off the final delimiter
int lengthToRemove = (i == separatedStream.Length - 1) ? delimiterEndBytes.Length : 0;
int contentByteArrayStartIndex = encoding.GetBytes(thisPieceAsString.Substring(0, indexOfStartOfContent)).Length;
byte[] fileData = new byte[separatedStream[i].Length - contentByteArrayStartIndex - lengthToRemove];
Array.Copy(separatedStream[i], contentByteArrayStartIndex, fileData, 0, separatedStream[i].Length - contentByteArrayStartIndex - lengthToRemove);
// save the fileData byte[] as the file
}
}