IOS NSURLSession后台上传 如何在后台上传大文件?

IOS NSURLSession Background Uploading how to upload Large Files in Background?

我想在后台上传 2-3 GB 的大文件(视频)到服务器,要求如下

第一种方法

  1. 如果互联网连接丢失并重新连接,上传应该会恢复

  2. 即使应用程序在后台,上传也应该继续

  3. 如果用户终止应用程序并返回,上传应该恢复

以上功能我已经实现了

  1. 用户select文件

  2. 将文件拆分为 1MB 的块并将磁盘上的所有块保存为文件

  3. 针对每个块文件创建上传任务并在后台会话中添加文件

以上方法有效但在某些情况下失败

  1. 如果文件大于 1GB 创建块并将块写入磁盘 抛出内存异常

  2. 如果我想上传 1GB 的文件,我需要额外的 1GB Space 来创建块

第二种方法

上传原始文件而不创建块,在这种情况下,如果网络连接丢失或用户终止应用程序,我将无法恢复上传

我的问题是什么是在后台上传大文件的最佳方式记住所有这些要点

我知道已经有人问过一些此类问题,但其中 none 回答了我的问题

我花了很多时间来实现这个但无法成功实现请帮助我或提出一些建议什么是完成上述要点的最佳方法

更新

我正在使用以下代码创建块 代码在 Xamarin.IOS 中,但如果有人在 Objective C 或 Swift

中提供解释,我很好
public static void SplitFileInChunks( UploadFileInfo UploadFile )
{
        int i = -1;

        long chunkSize = UploadHelper.chunkSize;
        nuint dataLength = (System.nuint)chunkSize; 

        //var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        string directoryPath = UploadHelper.UploadsDirectory;

        int chunkCount = 0;
        NSFileHandle fileHandleRead = NSFileHandle.OpenRead(UploadFile.FilePath);

        fileHandleRead.ReadInBackground();
        //fileHandleRead.WaitForDataInBackground();

        if (fileHandleRead == null)
            return;

        do
        {
            i++;
            ulong index = (ulong)(i * chunkSize);

            var filePath = Path.Combine(directoryPath, UploadFile.ContentGuide + "" + i.ToString());
            //fileHandleRead.SeekToFileOffset(index);

            NSData data = fileHandleRead.ReadDataOfLength(dataLength );
            Console.WriteLine(UploadFile.FileStatus);

            if (data.Length <= 0)
                continue;

            NSFileManager.DefaultManager.CreateFile(filePath, data, attr: null);


            NSError error;
            //data.Save(filePath, true, out error);

            chunkCount++;

            Console.WriteLine("Data Lenght" + data.Length);
            data.Dispose();
            Console.WriteLine("Chunk " + i);
        }

        while ( i * chunkSize <= UploadFile.Size && UploadFile.FileStatus != UploadFileStatus.Aborted );

        fileHandleRead.CloseFile();
        fileHandleRead.Dispose();

        Console.WriteLine("All Files Written sucessuflly");
        UploadFile.TotalChunksCount = chunkCount;

    }

那肯定行得通,但如果您能控制另一端的软件,您可以做得更好:

  • 在服务器端:

    • 提供仅提供唯一 ID 的上传开始端点 (URL)。
    • 提供一个上传数据端点,该端点采用唯一 ID、POST 正文和可选的起始字节偏移量,并将数据写入服务器上的临时文件。
    • 提供一个上传状态端点,该端点采用唯一 ID 和 returns 目前已存储在磁盘上的数据量。
    • 提供上传完成的端点。
  • 在客户端:

    • 调用起始端点并获取上传 ID。
    • 调用上传数据端点,开始发送数据。
    • 失败时,调用上传状态端点以查明服务器实际获得了多少数据。
    • 然后调用数据端点并从该偏移量开始发送数据,告诉服务器您从哪里开始。 (在服务器上,始终从那个偏移量开始写入文件,即使从那时起长度增加了,只是为了安全。)
    • 上传完成后,调用上传完成端点。

这种架构还可以相当轻松地显示状态栏。