IOS NSURLSession后台上传如何在后台上传大文件?
我想上传2-3 GB的大文件(视频)到后台服务器,要求如下 第一种方法IOS NSURLSession后台上传如何在后台上传大文件?,ios,nsurlsession,nsurlsessionuploadtask,Ios,Nsurlsession,Nsurlsessionuploadtask,我想上传2-3 GB的大文件(视频)到后台服务器,要求如下 第一种方法 如果internet连接丢失并重新连接,则应继续上载 即使应用程序处于后台,也应继续上载 如果用户终止应用程序并返回,则应继续上载 对于上述功能,我已经实现了什么 用户选择文件 将文件拆分为1MB的块,并将磁盘上的所有块保存为文件 针对每个区块文件创建上载任务,并在后台会话中添加该文件 上述方法有效,但在某些情况下失败 如果文件大于1GB,则在磁盘上创建块和写入块 抛出内存异常 如果我想上传1GB的文件,我需要额外的1GB空
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;
}
publicstaticvoidsplitfileinchunks(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;
nsfilehandlefilehandleread=NSFileHandle.OpenRead(UploadFile.FilePath);
fileHandleRead.ReadInBackground();
//FileHandlerRead.WaitForDataInBackground();
if(fileHandleRead==null)
返回;
做
{
i++;
ulong指数=(ulong)(i*chunkSize);
var filePath=Path.Combine(directoryPath,UploadFile.ContentGuide+“”+i.ToString());
//fileHandleRead.SeekToFileOffset(索引);
NSData data=FileHandlerRead.ReadDataOfLength(数据长度);
WriteLine(UploadFile.FileStatus);
如果(data.Length这肯定会起作用,但如果您控制另一端的软件,您可以做得更好:
- 在服务器端:
- 提供仅提供唯一ID的上载起始端点(URL)
- 提供一个上载数据端点,该端点采用唯一ID、POST正文和可选的起始字节偏移量,并将数据写入服务器上的临时文件
- 提供一个上载状态终结点,该终结点采用唯一ID并返回迄今为止存储在磁盘上的数据量
- 提供上载完成的终结点
- 在客户端:
- 调用起始端点并获取上载的ID
- 调用上载数据端点并开始发送数据
- 失败时,调用上载状态端点以了解服务器实际获得的数据量
- 然后调用数据端点并开始从该偏移量发送数据,告诉服务器您从何处开始。(在服务器上,始终从该偏移量开始将数据写入文件,即使从那时起长度增加了,只是为了安全。)
- 完成后,调用upload finished端点
这种体系结构还可以相当轻松地显示状态栏。是的,我使用的是后台会话,但为了在磁盘上保存块,我需要额外的空间,因为后台的NSURLsession只能与NSURL.FromFileName一起使用。据我所知,还有其他方法可以克服这一问题,如上载原始文件和支持恢复我曾尝试在AutoReleasePool
块中添加此功能,但这对我们来说并不幸运。不幸的是,除非您的数据完全适合RAM,否则我认为无法避免创建文件的截断副本。如果您预先对其进行分块,则可以创建当前分块的截断副本。无论如何,您的应用程序都必须是w确定并处理错误,然后重新启动传输。在某个时候,如果你的应用程序太频繁被唤醒,你将开始受到NSURLSession的惩罚,因此分块可能比不分块更糟糕。事实上,现在我想起来了,你可能可以使用基于流上载的NSURLSessionDownloadTask,但这取决于守护进程是否正确处理该问题。请首先尝试该方法,但如果失败,则必须创建文件的截断副本。我不明白第一种方法的含义,其次,我尝试使用此方法创建截断副本,但不幸的是,如果文件约为2-3 GB,并且我只上载了几次,则应用程序会崩溃t创建下载任务时,可以指定一个包含NSStream
的NSURLRequest
对象。如果使用getBoundStreamsWithBufferSize:inputStream:outputStream:
,则应用程序可以控制提供正文数据。然后,每次从文件中读取几兆字节的数据,并将其写入输出流,并在创建NSURLRequest
时传递输入流。基本上,在尝试发送数据之前打开流进行写入,等待获得“可用空间”事件,写入一些数据,并检查返回值以确定实际发送了多少数据。确保关闭