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); }
internal static bool ProcessStream(HttpContext context, Stream source, string fileId, string fileName, bool chunked, bool isFirstChunk, bool usePoll, string azureContainerName) { if (string.IsNullOrEmpty(azureContainerName)) { throw new Exception("AzureContainerName is not specified."); } FileHeaderInfo headerInfo = null; var states = new AjaxFileUploadStates(context, fileId); var uploaded = 0; using (var tmpStream = new MemoryStream()) { var totalBytesRead = 0; var done = false; var fileLength = 0; var blobClient = GetCloudBlobClient(); var blobContainer = blobClient.GetContainerReference(azureContainerName); blobContainer.CreateIfNotExists(); CloudBlockBlob blob = null; 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); // Create blob reference. blob = blobContainer.GetBlockBlobReference(fileName); if (!chunked || isFirstChunk) { blob.DeleteIfExists(); } var id = Convert.ToBase64String(Guid.NewGuid().ToByteArray()); blob.PutBlock(id, new MemoryStream(firstChunk, true), null); uploaded = firstChunk.Length; states.BlockList.Add(id); } } else { var length = index; // Reach in the end of stream, remove last boundary if (uploaded + index > fileLength) { length -= headerInfo.BoundaryDelimiterLength; done = true; } var id = Convert.ToBase64String(Guid.NewGuid().ToByteArray()); blob.PutBlock(id, new MemoryStream(chunk, 0, length, true), null); uploaded += length; states.BlockList.Add(id); } } // There is no byte to read anymore, upload is finished. if (done || index != chunk.Length) { if (blob != null) { blob.PutBlockList(states.BlockList); states.AzureBlobUri = blob.Uri.AbsoluteUri; } break; } } } return(true); }