示例#1
0
        private async Task InitFileReceiveEndpoints(IWebServer server, FileSendInfo fileInfo, FileSendProgressCalculator transferProgress)
        {
            await fileInfo.InitSlicingAsync();

            fileSliceSender = new FileSliceSender(fileInfo);
            transferProgress.AddFileSliceSender(fileSliceSender);
            fileSliceSender.SliceRequested += transferProgress.SliceRequestReceived;

            for (int i = 0; i < fileInfo.SlicesCount; i++)
            {
                server.AddResponseUrl($"/{fileInfo.UniqueKey}/{i}/", (Func <IWebServer, RequestDetails, Task <byte[]> >)fileSliceSender.GetFileSlice);
            }
        }
示例#2
0
        private static async Task <IFile> CreateFile(FileSendInfo fileInfo, Guid sessionKey, IFolder downloadFolder)
        {
            var file = await FileHelper.CreateFile(downloadFolder, fileInfo.FileName);

            if (file.Name != fileInfo.FileName) //File already existed, so new name generated for it. We should update database now.
            {
                await DataStorageProviders.HistoryManager.OpenAsync();

                DataStorageProviders.HistoryManager.UpdateFileName(sessionKey, fileInfo.FileName, file.Name, downloadFolder.Path);
                DataStorageProviders.HistoryManager.Close();
            }

            return(file);
        }
示例#3
0
        private async Task DownloadFile(FileSendInfo fileInfo, IFolder downloadRootFolder, string serverIp, Guid sessionKey, CancellationToken cancellationToken)
        {
            //TODO: Add a semaphore or sth to make sure two threads don't start writing on one file.

            IFolder downloadFolder = await FileHelper.CreateDirectoryIfNecessary(downloadRootFolder, fileInfo.RelativePath);

            await DataStorageProviders.HistoryManager.OpenAsync();

            var origFile = DataStorageProviders.HistoryManager.GetFileFromOriginalName(guid: sessionKey, originalFileName: fileInfo.FileName, path: downloadFolder.Path);

            DataStorageProviders.HistoryManager.Close();

            IFile file;
            uint  firstSliceToReceive = 0;

            if (origFile.DownloadStarted == false)
            {
                file = await CreateFile(fileInfo, sessionKey, downloadFolder);
            }
            else if (origFile.Completed == true)
            {
                return;
            }
            else
            {
                file = await FileHelper.GetFile(downloadFolder, origFile.Name);

                var stats = await file.GetFileStats();

                if (stats.Length == (long)(fileInfo.SlicesCount * fileInfo.SliceMaxLength + fileInfo.LastSliceSize))
                {
                    //It's already finished.
                    await DataStorageProviders.HistoryManager.OpenAsync();

                    DataStorageProviders.HistoryManager.MarkFileAsCompleted(sessionKey, file.Name, downloadFolder.Path);
                    DataStorageProviders.HistoryManager.Close();
                    return;
                }
                else if (stats.Length % (long)fileInfo.SliceMaxLength != 0)
                {
                    //Invalid size. Will start over.
                    await file.DeleteAsync();

                    file = await CreateFile(fileInfo, sessionKey, downloadFolder);

                    firstSliceToReceive = 0;
                }
                else
                {
                    firstSliceToReceive = (uint)(stats.Length / (long)fileInfo.SliceMaxLength);
                    if (firstSliceToReceive > 0)
                    {
                        progressCalculator.SliceReceived(fileInfo, firstSliceToReceive - 1);
                    }
                }
            }

            ulong totalBytesReceived = 0;

            using (var stream = await file.OpenAsync(PCLStorage.FileAccess.ReadAndWrite))
            {
                stream.Seek(stream.Length, SeekOrigin.Begin);

                await DataStorageProviders.HistoryManager.OpenAsync();

                DataStorageProviders.HistoryManager.SetDownloadStarted(sessionKey, file.Name, downloadFolder.Path);
                DataStorageProviders.HistoryManager.Close();

                for (uint i = firstSliceToReceive; i < fileInfo.SlicesCount; i++)
                {
                    string url = $"http://{serverIp}:{Constants.CommunicationPort}/{fileInfo.UniqueKey}/{i}/";

                    if (cancellationToken.IsCancellationRequested)
                    {
                        throw new ReceiveCancelledException();
                    }

                    byte[] buffer = await HttpHelper.DownloadDataFromUrl(url, cancellationToken : cancellationToken);

                    if (cancellationToken.IsCancellationRequested)
                    {
                        throw new ReceiveCancelledException();
                    }

                    int expectedLength;
                    if (i == (fileInfo.SlicesCount - 1))
                    {
                        expectedLength = (int)(fileInfo.FileSize % fileInfo.SliceMaxLength);
                    }
                    else
                    {
                        expectedLength = (int)fileInfo.SliceMaxLength;
                    }

                    if (buffer.Length != expectedLength)
                    {
                        Debug.WriteLine("Slice length violation! Will retry...");
                        i--;
                        continue;
                    }
                    await stream.WriteAsync(buffer, 0, buffer.Length);

                    await stream.FlushAsync();

                    totalBytesReceived += (ulong)expectedLength;

                    progressCalculator.SliceReceived(fileInfo, i);
                }
            }

            await DataStorageProviders.HistoryManager.OpenAsync();

            DataStorageProviders.HistoryManager.MarkFileAsCompleted(sessionKey, file.Name, downloadFolder.Path);
            DataStorageProviders.HistoryManager.Close();
        }
 internal void SliceReceived(FileSendInfo file, uint receivedSlice)
 {
     SliceReceived(file.UniqueKey, receivedSlice);
 }