iOS开发基础42-网络编程之文件下载与处理
1.iOS开发基础1-第一个iOS程序2.iOS开发基础2-基础控件3.iOS开发基础6-懒加载、Plist 文件操作、字典转模型、自定义 View 详解4.iOS开发基础5-UIButton5.iOS开发基础4-图像资源6.iOS开发基础3-UIImage7.iOS开发基础14-KVC的应用与底层逻辑8.iOS开发基础13-深入理解 UITableView(二)9.iOS开发基础12-深入理解UITableView(一)10.iOS开发基础11-屏幕适配、Autolayout及 Masonry 框架11.iOS开发基础10-UIButton内边距和图片拉伸模式12.iOS开发基础9-提示框(UIAlertController)13.iOS开发基础8-UIScrollView14.iOS开发基础7-自定义构造方法、layoutSubviews、Xib文件与自定义View15.iOS开发基础30-UITabBarController16.iOS开发基础29-触摸事件及手势识别17.iOS开发基础28-数据存储与沙盒机制18.iOS开发基础27-导航控制器入栈与出栈机制及微博个人详情页19.iOS开发基础26-空20.iOS开发基础25-ARC和MRC深入探析21.iOS开发基础24-UIPickerView、UITextField、KVC、UIDatePicker、控制器及导航控制器22.iOS开发基础23-iOS开发中的Info.plist、UIApplication及其Delegate、UIWindow详解23.iOS开发基础22-键盘通知在iOS开发中的应用24.iOS开发基础21-深入理解通知、代理、KVO和Block在iOS开发中的应用25.iOS开发基础20-UITableView的全局及局部刷新、左滑操作与批量删除26.iOS开发基础19-深入理解和实现不等高的 UITableViewCell27.iOS开发基础18-深入理解 Objective-C Runtime 机制28.iOS开发基础16-使用 `NSTimer` 时避免内存泄露的技巧和最佳实践29.iOS开发基础15-KVO的应用与底层逻辑30.iOS开发基础65-iPad 开发指南31.iOS开发基础64-二维码32.iOS开发基础63-AVFoundation/MediaPlayer33.iOS开发基础62-音频播放34.iOS开发基础61-通讯录35.iOS开发基础60-传感器36.iOS开发基础59-内存优化37.iOS开发基础58-支付宝集成指南38.iOS开发基础57-换肤功能与静态库开发指南39.iOS开发基础56-UIDynamic物理引擎40.iOS开发基础55-利用 UIWindow 实现快速滚动到界面顶部41.iOS开发基础54-CoreLocation42.iOS开发基础53-MapKit 框架43.iOS开发基础47-iOS键盘44.iOS开发基础46-数据安全与HTTPS保护详解45.iOS开发基础45-UIWebview46.iOS开发基础44-网络编程之NSURLSession&AFN47.iOS开发基础43-CocoaPods
48.iOS开发基础42-网络编程之文件下载与处理
49.iOS开发基础41-网络编程之JSON和XML50.iOS开发基础40-网络编程之NSURLConnection51.iOS开发基础39-RunLoop52.iOS开发基础38-多线程之多图片下载及缓存处理53.iOS开发基础37-多线程之NSOperation54.iOS开发基础36-多线程之GCD55.iOS开发基础35-多线程之NSThread56.iOS开发基础34-多线程57.iOS开发基础33-核心动画(二)58.iOS开发基础33-核心动画(一)59.iOS开发基础32-Quartz2D(二)60.iOS开发基础32-Quartz2D(一)61.iOS开发基础31-Modal 与 Push 详解62.iOS开发基础76-iOS 开发中的属性修饰符详解63.iOS开发基础75-iOS开发中的Block深度解析64.iOS开发基础74-Swift他来了65.iOS开发基础73-24种性能优化技巧66.iOS开发基础72-Xcode 7 升级后的问题与解决方案详解67.iOS开发基础71-应用中的 StatusBar 详解68.iOS开发基础70-TCP与UDP69.iOS开发基础69-应用开发中的 Controller 间通信模式70.iOS开发基础68-图片轮播71.iOS开发基础67-流水布局相册缩放72.iOS开发基础66-UISearchBar 控件指南73.iOS开发基础78-iOS 国际化在iOS应用开发中,文件下载是一个常见的需求,可能涉及下载小图片、音频文件或者大型的视频、压缩包等。本文将详细介绍如何在iOS中进行文件下载,包括小文件和大文件的下载处理,文件的压缩/解压缩,获取文件MIMEType,以及文件上传和断点续传。
一、小文件下载
对于小文件的下载,可以直接使用NSURLConnection
的异步请求方法:
NSURL *url = [NSURL URLWithString:@"http://example.com/path/to/file.png"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (data) {
UIImage *image = [UIImage imageWithData:data];
// 将图片用于界面展示或保存等操作
} else {
// 错误处理
NSLog(@"Download failed with error: %@", connectionError);
}
}];
二、大文件下载
对于大文件的下载,直接使用内存处理会导致内存暴涨,因此需要更高效的方式来处理大文件的下载。下面介绍三种处理方式:
1. 使用 NSMutableData
这种方法简单但会导致内存暴涨,不推荐:
@property (nonatomic, strong) NSMutableData *fileData;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.fileData appendData:data];
}
2. 使用 NSFileHandle
NSFileHandle
是专门用于文件操作的类,通过创建文件句柄,将下载的数据写入文件,节省内存:
@interface ViewController ()<NSURLConnectionDataDelegate>
@property (nonatomic, strong) NSFileHandle *fileHandle;
@property (nonatomic, copy) NSString *filePath;
@property (nonatomic, assign) NSUInteger totalLength;
@property (nonatomic, assign) NSUInteger currentLength;
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:@"http://example.com/path/to/file.mp4"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSString *fileName = response.suggestedFilename;
self.filePath = [[self documentsDirectory] stringByAppendingPathComponent:fileName];
[[NSFileManager defaultManager] createFileAtPath:self.filePath contents:nil attributes:nil];
self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.filePath];
self.totalLength = response.expectedContentLength;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.fileHandle seekToEndOfFile];
[self.fileHandle writeData:data];
self.currentLength += data.length;
self.progressView.progress = (CGFloat)self.currentLength / self.totalLength;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self.fileHandle closeFile];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"Download failed with error: %@", error);
}
- (NSString *)documentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
}
@end
3. 使用 NSOutputStream
NSOutputStream
是另一种处理大文件下载的方式,性能良好且内存占用少:
@property (nonatomic, strong) NSOutputStream *outputStream;
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
self.filePath = [[self documentsDirectory] stringByAppendingPathComponent:response.suggestedFilename];
self.outputStream = [NSOutputStream outputStreamToFileAtPath:self.filePath append:YES];
[self.outputStream open];
self.totalLength = response.expectedContentLength;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.outputStream write:data.bytes maxLength:data.length];
self.currentLength += data.length;
self.progressView.progress = (CGFloat)self.currentLength / self.totalLength;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self.outputStream close];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"Download failed with error: %@", error);
}
三、文件压缩/解压缩(使用第三方框架ZipArchive)
使用 ZipArchive
框架可以快速实现文件的压缩和解压缩:
压缩文件
NSArray *files = @[@"path/to/file1", @"path/to/file2"];
NSString *zipPath = @"path/to/archive.zip";
[SSZipArchive createZipFileAtPath:zipPath withFilesAtPaths:files];
解压缩文件
NSString *zipPath = @"path/to/archive.zip";
NSString *destinationPath = @"path/to/destination";
[SSZipArchive unzipFileAtPath:zipPath toDestination:destinationPath];
四、MIMEType(获取文件类型)
获取文件的MIMEType有两种方法:使用 NSURLConnection
和 C语言API。
使用 NSURLConnection
- (NSString *)MIMETypeForURL:(NSURL *)url {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
return response.MIMEType;
}
使用 C语言API
+ (NSString *)mimeTypeForFileAtPath:(NSString *)path {
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
return nil;
}
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)[path pathExtension], NULL);
CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType);
CFRelease(UTI);
if (!MIMEType) {
return @"application/octet-stream";
}
return (__bridge_transfer NSString *)MIMEType;
}
五、文件上传
文件上传需要构建特定的HTTP请求头和请求体。
设置请求头
[request setValue:@"multipart/form-data; boundary=Boundary" forHTTPHeaderField:@"Content-Type"];
构建请求体
NSMutableData *body = [NSMutableData data];
NSString *boundary = @"Boundary";
// 文件参数
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimeType] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:fileData];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 非文件参数
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"param\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"paramValue" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// 结束标记
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = body;
发送请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (data) {
// 上传成功处理
} else {
// 错误处理
NSLog(@"Upload failed with error: %@", connectionError);
}
}];
六、断点下载(续传)
断点下载的关键是通过自定义HTTP请求的头部的 Range
属性来实现:
NSURL *url = [NSURL URLWithString:@"http://example.com/path/to/file.mp4"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:@"bytes=20000-" forHTTPHeaderField:@"Range"];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// 将数据写入文件
[self writeToFile:data filePath:@"path/to/local/file.mp4"];
写入数据到文件
- (void)writeToFile:(NSData *)data filePath:(NSString *)filePath {
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
}
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
[fileHandle seekToEndOfFile];
[fileHandle writeData:data];
[fileHandle closeFile];
}
将来的你会感谢今天如此努力的你!
版权声明:本文为博主原创文章,未经博主允许不得转载。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!