public void Perform()
        {
            using (var client = ClientModel.Get())
            {
                var chat = client.Chat;
                var room = chat.GetRoom(_roomName);

                if (chat.IsFileDownloading(_fileId))
                {
                    throw new ModelException(ErrorCode.FileAlreadyDownloading, _fileId);
                }

                var file = room.TryGetFile(_fileId);
                if (file == null)
                {
                    throw new ModelException(ErrorCode.FileInRoomNotFound);
                }

                if (chat.User.Equals(file.Id.Owner))
                {
                    throw new ModelException(ErrorCode.CantDownloadOwnFile);
                }

                chat.AddFileDownload(new DownloadingFile(file, _savePath));

                var sendingContent = new ClientReadFilePartCommand.MessageContent
                {
                    File              = file.ToDto(),
                    Length            = AsyncClient.DefaultFilePartSize,
                    RoomName          = _roomName,
                    StartPartPosition = 0,
                };

                ClientModel.Peer.SendMessage(file.Id.Owner, ClientReadFilePartCommand.CommandId, sendingContent);
            }
        }
        protected override void OnRun(MessageContent content, CommandArgs args)
        {
            if (content.File == null)
            {
                throw new ArgumentNullException("content.File");
            }

            if (args.Unpacked.RawData == null)
            {
                throw new ArgumentNullException("args.Unpacked.RawData");
            }

            if (args.Unpacked.RawLength <= 0)
            {
                throw new ArgumentException("args.Unpacked.RawLength <= 0");
            }

            if (content.StartPartPosition < 0)
            {
                throw new ArgumentException("content.StartPartPosition < 0");
            }

            if (string.IsNullOrEmpty(content.RoomName))
            {
                throw new ArgumentException("content.RoomName");
            }

            var fileId   = content.File.Id;
            var progress = 0;

            using (var client = ClientModel.Get())
            {
                var chat = client.Chat;

                var downloading = chat.TryGetFileDownload(fileId);
                if (downloading == null)
                {
                    return;
                }

                var stream         = downloading.WriteStream;
                var filePart       = args.Unpacked.RawData;
                var filePartLength = args.Unpacked.RawLength;

                if (stream.Position == content.StartPartPosition)
                {
                    stream.Write(filePart, 0, filePartLength);
                }

                if (stream.Position >= content.File.Size)
                {
                    chat.RemoveFileDownload(fileId);

                    progress = 100;
                }
                else
                {
                    var sendingContent = new ClientReadFilePartCommand.MessageContent
                    {
                        File              = content.File,
                        Length            = AsyncClient.DefaultFilePartSize,
                        RoomName          = content.RoomName,
                        StartPartPosition = stream.Position,
                    };

                    ClientModel.Peer.SendMessage(args.ConnectionId, ClientReadFilePartCommand.CommandId, sendingContent);

                    progress = (int)((stream.Position * 100) / content.File.Size);
                }
            }

            ClientModel.Notifier.DownloadProgress(new FileDownloadEventArgs(content.RoomName, fileId, progress));
        }