Пример #1
0
        public void DownloadFile(string remoteFilepath, string localFilepath)
        {
            remoteFilepath = Path.IsPathRooted(remoteFilepath) ? remoteFilepath : Path.Combine(CurrentFolder, remoteFilepath);

            string remoteFilename  = Path.GetFileName(remoteFilepath);
            string remoteDirectory = remoteFilepath.Substring(0, remoteFilepath.Length - remoteFilename.Length);

            var lsResponse = remoteExecutor.Execute(new ListDirectoryClientRequest
            {
                Path = remoteDirectory,
                AuthenticationToken = authenticationToken
            });

            RemoteFile remoteFileInfo = lsResponse.RemoteFiles.FirstOrDefault(x => x.Filename == remoteFilename);

            if (remoteFileInfo == null)
            {
                throw new CustomException("File does not exist on the remote machine.");
            }

            int partLength = 512 * 1024;
            ParallelFileDownloader parallelFileDownloader = new ParallelFileDownloader(remoteFileInfo.Size, partLength);

            Stopwatch sw = Stopwatch.StartNew();

            using (ParallelFileWriter parallelFileWriter = new ParallelFileWriter(localFilepath))
                using (ConsoleStatusWriter statusWriter = new ConsoleStatusWriter("Downloading...", remoteFileInfo.Size))
                {
                    parallelFileDownloader.FilePartDownloadedEvent += (partNumber, data) => ParallelFileDownloader_FilePartDownloadedEvent(parallelFileWriter, statusWriter, partNumber, data);

                    IRemoteRequestExecutor[] executors = GetHelperRequestExecutors(4);

                    foreach (var helperExecutor in executors)
                    {
                        parallelFileDownloader.StartNew((offset, count) => helperExecutor.Execute(new DownloadFileRequest
                        {
                            AuthenticationToken = authenticationToken,
                            Filepath            = remoteFilepath,
                            Offset = offset,
                            Count  = count
                        }).Data);
                    }

                    parallelFileDownloader.Wait();
                }

            sw.Stop();
            WriteStatistics(sw.ElapsedMilliseconds, remoteFileInfo.Size);
        }
Пример #2
0
        public void ReadCallback(IAsyncResult ar)
        {
            //int fileNameLen = 1;
            //String content = String.Empty;
            StateObject tempState = (StateObject)ar.AsyncState;
            Socket      handler   = tempState.workSocket;
            int         bytesRead = handler.EndReceive(ar);

            if (bytesRead <= 0)
            {
                return;
            }

            counter.AddBytes((uint)bytesRead);

            if (isFirstPacket)
            {
                try
                {
                    // gets the first byte
                    byte[] firstByte = new byte[1];
                    firstByte = tempState.buffer.Take(1).ToArray();

                    // first byte has a value 0 - 255
                    fileNameLength = Convert.ToInt32(firstByte[0]);

                    // a fileName cannot be more then 255 characters because a byte cannot have have a higher value...
                    if (fileNameLength > 255)
                    {
                        // filename is not valid...
                        // this should not happen, should somehow at least validate the first packet to ensure
                        // it contain the right information...
                        return;
                        //fileNameLength = 255;
                    }

                    // TODO:
                    // check if fileName is valid
                    // if file already exist (conflict)

                    fileName = Encoding.ASCII.GetString(tempState.buffer, 1, fileNameLength);
                    //receivePath += "\\" + fileName;

                    // after the file name comes the size of the file
                    // should be a long
                    // that is 64 bit = 8 byte
                    byte[] fileSizeB = tempState.buffer.Skip(1 + fileNameLength).Take(8).ToArray();
                    fileSize = BitConverter.ToInt64(fileSizeB, 0);

                    // set total to be received
                    totalBytesToBeReceived = fileNameLength + fileSize + 9;

                    // TODO:
                    // get FileInfo object

                    // TODO:
                    // start download counter, datetime, total filesize to download etc
                    // get MD5 hash or other hash of file
                    // make sure all meta data and other stuff is actually sent
                    // calculate hash of when file has been received and written to a file here
                    // close socket and stop thread when entire file has been written

                    // start timer that will execute an event every 1 sec
                    // that shows mb/s kb/s etc
                    timer = new System.Timers.Timer()
                    {
                        Interval = 1000, Enabled = true
                    };
                    timer.Elapsed += timer_Elapsed;
                    timer.Start();
                }
                catch (InvalidCastException castError)
                {
                    // was not able to find file size
                    Console.WriteLine(castError.Message);
                    return;
                }
                catch (Exception error)
                {
                    Console.WriteLine(error.Message);
                    return;
                }
            }

            BinaryWriter writer = null;

            try
            {
                // TODO:
                // double check that file path is correct

                // TODO:
                // only open file while it is not in use
                // wait until file is ready to be written to

                if (isFirstPacket)
                {
                    // old way
                    //writer = new BinaryWriter(File.Open(savePathAndFileName, FileMode.Append));

                    string savePathAndFileName = receivePath + "\\" + fileName;

                    // creates a thread pool using BlockingCollection
                    // this will allow a queue of max 200 threads waiting to write to the file
                    // if more than 200 threads are created, they are blocked and wait until the '
                    // queue is free
                    fileWriter = new ParallelFileWriter(savePathAndFileName, 200);

                    // the first packet contain information that should not be written to the file itself so
                    // if first packet then increase the index to size of fileName + one byte
                    // since we increase the index, we need to reduce the count by the same amount

                    // + 1 byte for size of fileName byte
                    // + 8 bytes for 64 bit long with file size
                    // shift = 9 bytes + fileName
                    int shift = fileNameLength + 9;
                    //writer.Write(tempState.buffer, shift, bytesRead - shift);

                    byte[] data = new byte[bytesRead - shift];
                    Array.Copy(tempState.buffer, shift, data, 0, bytesRead - shift);

                    fileWriter.Write(data);

                    isFirstPacket = false;

                    // set fileName, but do not trigger event
                    FileTransferEvents.filename = fileName;
                }
                else
                {
                    byte[] data = new byte[bytesRead];
                    Array.Copy(tempState.buffer, 0, data, 0, bytesRead);

                    fileWriter.Write(data);

                    //writer.Write(tempState.buffer, 0, bytesRead);
                }

                // TODO:
                // for each byte that has been read, update download counter
                // based on time and bytes received both mb/s and percentage downloaded
                // should be calculated in real time
                // create event

                // add to written files
                totalBytesReceived += bytesRead;

                // TODO:
                // check if all bytes has been read and transfer is complete
                if (totalBytesReceived == totalBytesToBeReceived)
                {
                    // trigger file received event
                    FileTransferEvents.FileReceived = fileName;

                    // reset connection
                    // set everything back to default and wait for new file
                    resetConnection();
                }
            }
            catch (Exception error)
            {
                Console.WriteLine(error.Message);
                Thread.Sleep(30);
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }



                // triggers event with long of bytes written
                //FileTransferEvents.BytesReceived = written;

                // this method starts a new  AsyncCallback(ReadCallback)
                // and this method is ReadCallback so it works as a recursive method
                handler.BeginReceive(tempState.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), tempState);

                //Thread.CurrentThread.Interrupt();
            }
        }
Пример #3
0
 private void ParallelFileDownloader_FilePartDownloadedEvent(ParallelFileWriter writer, ConsoleStatusWriter statusWriter, int partNumber, byte[] data)
 {
     writer.WritePart(partNumber, data);
     statusWriter.Update(data.Length);
 }
Пример #4
0
        public void ReadCallback(IAsyncResult ar)
        {
            StateObject tempState = (StateObject)ar.AsyncState;
            Socket      handler   = tempState.workSocket;

            // handle connection problems
            int bytesRead = 0;

            try
            {
                bytesRead = handler.EndReceive(ar);
            }
            catch (SocketException socketError)
            {
                Console.WriteLine("Socket error while transfering: " + socketError.Message);
                Console.WriteLine("Reseting connection...");
                resetConnection();
            }
            catch (Exception error)
            {
                Console.WriteLine("Error while transfering: " + error.Message);
                return;
            }

            if (bytesRead <= 0)
            {
                return;
            }

            // add to counter
            counter.AddBytes((uint)bytesRead);

            if (isFirstPacket)
            {
                try
                {
                    // gets the first byte
                    byte[] firstByte = new byte[1];
                    firstByte = tempState.buffer.Take(1).ToArray();

                    // first byte has a value 0 - 255
                    fileNameLength = Convert.ToInt32(firstByte[0]);

                    // a fileName cannot be more then 255 characters because a byte cannot have have a higher value...
                    if (fileNameLength > 255)
                    {
                        // filename is not valid...
                        // this should not happen, should somehow at least validate the first packet to ensure
                        // it contain the right information...
                        return;
                        //fileNameLength = 255;
                    }

                    // TODO:
                    // check if fileName is valid

                    // Windows 1252 encoding
                    Encoding encoding1252 = Encoding.GetEncoding(1252);
                    fileName = encoding1252.GetString(tempState.buffer, 1, fileNameLength);

                    // after the file name comes the size of the file
                    // should be a long
                    // that is 64 bit = 8 byte
                    byte[] fileSizeB = tempState.buffer.Skip(1 + fileNameLength).Take(8).ToArray();
                    fileSize = BitConverter.ToInt64(fileSizeB, 0);

                    // get md5 hash
                    // md5 hash is 16 bytes = 128 bit
                    md5 = tempState.buffer.Skip(1 + fileNameLength + 8).Take(16).ToArray();

                    // set total to be received
                    totalBytesToBeReceived = fileNameLength + fileSize + 9 + 16;

                    // TODO:
                    // get FileInfo object

                    // TODO:
                    // start download counter, datetime, total filesize to download etc
                    // get MD5 hash or other hash of file
                    // make sure all meta data and other stuff is actually sent
                    // calculate hash of when file has been received and written to a file here
                    // close socket and stop thread when entire file has been written

                    // start timer that will execute an event every 1 sec
                    // that shows mb/s kb/s etc
                    timer = new System.Timers.Timer()
                    {
                        Interval = 1000, Enabled = true
                    };
                    timer.Elapsed += timer_Elapsed;
                    timer.Start();
                }
                catch (InvalidCastException castError)
                {
                    // was not able to find file size
                    Console.WriteLine(castError.Message);
                    return;
                }
                catch (Exception error)
                {
                    Console.WriteLine(error.Message);
                    return;
                }
            }

            BinaryWriter writer = null;

            try
            {
                // TODO:
                // only open file while it is not in use
                // wait until file is ready to be written to

                if (isFirstPacket)
                {
                    // old way
                    //writer = new BinaryWriter(File.Open(savePathAndFileName, FileMode.Append));

                    // TODO:
                    // check that file name and path is correct

                    string savePathAndFileName = receivePath + "\\" + fileName;

                    // check if file already exist
                    // if it does, simply append to the file
                    if (File.Exists(savePathAndFileName))
                    {
                        // TODO:
                        // check if md5 hash of existing file is correct
                        // if so, stop transfer

                        // TODO:
                        // if md5 hash is not the same, check file size of existing file
                        // if its bigger than it's supposed too, remove it
                        // if not, start appending to the file


                        Console.WriteLine("File already exist, appending to file...");
                        fileWriter = new ParallelFileWriter(savePathAndFileName, 200, true);
                    }
                    else
                    {
                        // creates a thread pool using BlockingCollection
                        // this will allow a queue of max 200 threads waiting to write to the file
                        // if more than 200 threads are created, they are blocked and wait until the '
                        // queue is free
                        fileWriter = new ParallelFileWriter(savePathAndFileName, 200);
                    }

                    // the first packet contain information that should not be written to the file itself so
                    // if first packet then increase the index to size of fileName + one byte
                    // since we increase the index, we need to reduce the count by the same amount

                    // + 1 byte for size of fileName byte
                    // + 8 bytes for 64 bit long with file size
                    // + 16 bytes for md5 hash
                    // shift = 9 bytes + fileName
                    int shift = fileNameLength + 9 + 16;
                    //writer.Write(tempState.buffer, shift, bytesRead - shift);

                    byte[] data = new byte[bytesRead - shift];
                    Array.Copy(tempState.buffer, shift, data, 0, bytesRead - shift);

                    fileWriter.Write(data);

                    isFirstPacket = false;

                    // set fileName, but do not trigger event
                    FileTransferEvents.filename = fileName;
                }
                else
                {
                    byte[] data = new byte[bytesRead];
                    Array.Copy(tempState.buffer, 0, data, 0, bytesRead);

                    fileWriter.Write(data);

                    //writer.Write(tempState.buffer, 0, bytesRead);
                }

                // add to written files
                totalBytesReceived += bytesRead;

                // check if all bytes has been read and transfer is complete
                if (totalBytesReceived == totalBytesToBeReceived)
                {
                    // trigger file received event
                    FileTransferEvents.FileReceived = fileName;

                    // get file location
                    string savePathAndFileName = receivePath + "\\" + fileName;

                    // reset connection
                    // set everything back to default and wait for new file
                    resetConnection();

                    // close file writer so we can access file again
                    if (writer != null)
                    {
                        writer.Close();
                    }

                    // complete writing tasks and threads
                    fileWriter.Dispose();

                    Console.WriteLine("Calculating md5 hash of received file...");

                    // get md5 hash
                    ChecksumCalc checksum         = new ChecksumCalc();
                    byte[]       md5AfterTransfer = checksum.GetMD5Checksum(savePathAndFileName);

                    // check if md5 received is identical to md5 calculated after transfer
                    bool isIdentical = checksum.checkIfHashisIdentical(md5, md5AfterTransfer);

                    if (isIdentical)
                    {
                        // the hash received before the file transfer is identical to the
                        // hash calculated with the new file
                        Console.WriteLine("SUCCESS: md5 hash match the md5 of received file");
                    }
                    else
                    {
                        // delete file?
                        Console.WriteLine("ERROR: File is corrupt, md5 hash does NOT match the md5 of the file received");
                    }
                }
            }
            catch (Exception error)
            {
                Console.WriteLine(error.Message);
                Thread.Sleep(30);
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }

                // triggers event with long of bytes written
                //FileTransferEvents.BytesReceived = written;

                // this method starts a new  AsyncCallback(ReadCallback)
                // and this method is ReadCallback so it works as a recursive method
                try
                {
                    handler.BeginReceive(tempState.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), tempState);
                }
                catch (SocketException socketError)
                {
                    Console.WriteLine("Socket error while transfering: " + socketError.Message);
                    Console.WriteLine("Reseting connection...");
                    resetConnection();
                }
                catch (Exception error)
                {
                    Console.WriteLine("Error while transfering: " + error.Message);
                }
            }
        }