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);
        }
Esempio n. 2
0
        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);
        }