public static bool ProcessStream(HttpContext context, Stream source, string fileId, string fileName, bool chunked, bool isFirstChunk, bool usePoll)
{
FileHeaderInfo headerInfo = null;
Stream destination = null;
var states = new AjaxFileUploadStates(context, fileId);
using (var tmpStream = new MemoryStream()) {
var totalBytesRead = 0;
var done = false;
var fileLength = 0;
while (true)
{
if (states.Abort)
{
return(false);
}
// read per chunk
var chunkSize = usePoll ? ChunkSizeForPolling : ChunkSize;
if (chunkSize > source.Length)
{
chunkSize = (int)source.Length;
if (usePoll)
{
states.FileLength = chunkSize;
}
}
var chunk = new byte[chunkSize];
var index = 0;
while (index < chunk.Length)
{
var bytesRead = source.Read(chunk, index, chunk.Length - index);
if (bytesRead == 0)
{
break;
}
if (usePoll)
{
states.Uploaded += bytesRead;
}
index += bytesRead;
}
totalBytesRead += index;
// Byte is not empty nor reach end of file
if (index != 0)
{
// Keep seeking header info until it's found
if (headerInfo == null)
{
// Append every first byte into temporary memory stream
tmpStream.Write(chunk, 0, index);
// Load it all into byte array, and try parse it so we can get header info
var firstBytes = tmpStream.ToArray();
// Find header info from first bytes.
headerInfo = MultipartFormDataParser.ParseHeaderInfo(firstBytes, Encoding.UTF8);
// If it's found, then start writing to file.
if (headerInfo != null)
{
// Calculate total file length.
fileLength = ((int)(source.Length - headerInfo.BoundaryDelimiterLength) - headerInfo.StartIndex);
if (usePoll)
{
states.FileLength = fileLength;
}
// Only write file data, so not all bytes are written.
var lengthToWrite = totalBytesRead - headerInfo.StartIndex;
if (lengthToWrite > fileLength)
{
lengthToWrite = fileLength;
done = true;
}
// Get first chunk of file data.
var firstChunk = new byte[lengthToWrite];
Buffer.BlockCopy(firstBytes, headerInfo.StartIndex, firstChunk, 0, lengthToWrite);
var tmpFilePath = GetTempFilePath(fileId, fileName);
AjaxFileUpload.CheckTempFilePath(tmpFilePath);
CreateTempFilePathFolder(tmpFilePath);
if (!chunked || isFirstChunk)
{
// Create new file, if this is a first chunk or file is not chunked.
destination = new FileStream(tmpFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
}
else
{
// Append data to existing teporary file for next chunks
destination = new FileStream(tmpFilePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
}
// Writing it now.
destination.Write(firstChunk, 0, lengthToWrite);
}
}
else
{
var length = index;
// Reach in the end of stream, remove last boundary
if (destination.Length + index > fileLength)
{
length -= headerInfo.BoundaryDelimiterLength;
done = true;
}
destination.Write(chunk, 0, length);
}
}
else
{
break;
}
// There is no byte to read anymore, upload is finished.
if (done || index != chunk.Length)
{
if (destination != null)
{
destination.Close();
destination.Dispose();
}
break;
}
}
}
return(true);
}