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

时间:2017-04-24 14:34:55

标签: ios nsurlsession nsurlsessionuploadtask

我希望在后台将2-3 GB的大文件(视频)上传到服务器,并满足以下要求

第一种方法

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

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

  3. 如果用户杀死了应用程序并返回

  4. ,则应继续上传

    以上功能我已经实现了

    1. 用户选择文件

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

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

    4. 上述方法有效但在某些情况下失败

      1. 如果文件大于1GB通过内存异常在磁盘上创建块和写入块

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

      3. 第二种方法

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

        我的问题是在背景中上传大文件的最佳方法是什么?记住所有这些要点

        我知道有一些问题已经被问过,但没有人回答我的问题

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

        更新

        我使用以下代码创建块 代码在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;
        
            }
        

1 个答案:

答案 0 :(得分:1)

这肯定会奏效,但如果你能控制另一端的软件,你可以做得更好:

  • 在服务器端:

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

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

此架构还可以非常轻松地显示状态栏。