首页 > 系统 > iOS > 正文

ios 文件上传, post数据

2019-11-07 23:14:10
字体:
来源:转载
供稿:网友

ios 文件上传, post数据 

2014-07-22 16:44 43110人阅读 评论(2) 收藏 举报 分类:

一、文件下载

获取资源文件大小有两张方式

1、

[objc] view plain copy 在CODE上查看代码片HTTP HEAD方法  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:kTimeout];  request.HTTPMethod = @"HEAD";  [NSURLConnection sendAsynchronousRequest:request queue:self.myQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {      NSLog(@"%@", response);      NSLog(@"---------------");      NSLog(@"%@", data);  }];  运行测试代码可以发现,HEAD方法只是返回资源信息,而不会返回数据体  应用场景:  获取资源Mimetype  获取资源文件大小,用于端点续传或多线程下载  2

[objc] view%20plain copy 使用块代码获取网络资源大小的方法  - (void)fileSizeWithURL:(NSURL *)url completion:(void (^)(long long contentLength))completion  {      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:kTimeout];      request.HTTPMethod = @"HEAD";       NSURLResponse *response = nil;      [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];            completion(response.expectedContentLength);  }  确定每次下载数据包的伪代码实现

[objc] view%20plain copy - (void)downloadFileWithURL:(NSURL *)url  {      [self fileSizeWithURL:url completion:^(long long contentLength) {          NSLog(@"文件总大小:%lld", contentLength);                  // 根据大小下载文件                 while (contentLength > kDownloadBytes) {              NSLog(@"每次下载长度:%lld", (long long)kDownloadBytes);              contentLength -= kDownloadBytes;          }          NSLog(@"最后下载字节数:%lld", contentLength);      }];  }  HTTP%20Range的示例通过设置Range可以指定每次从网路下载数据包的大小Range示例bytes=0-499%20从0到499的头500个字节bytes=500-999%20从500到999的第二个500字节bytes=500-%20从500字节以后的所有字节bytes=-500%20最后500个字节bytes=500-599,800-899%20同时指定几个范围Range小结-%20用于分隔前面的数字表示起始字节数后面的数组表示截止字节数,没有表示到末尾,%20用于分组,可以一次指定多个Range,不过很少用

[objc] view%20plain copy 分段Range代码实现  long long fromBytes = 0;  long long toBytes = 0;  while (contentLength > kDownloadBytes) {      toBytes = fromBytes + kDownloadBytes - 1;      NSString *range = [NSString stringWithFormat:@"bytes=%lld-%lld", fromBytes, toBytes];      NSLog(@"range %@", range);      fromBytes += kDownloadBytes;      contentLength -= kDownloadBytes;  }  fromBytes = fromBytes + contentLength - 1;  NSString *range = [NSString stringWithFormat:@"bytes=%lld-%lld", fromBytes, toBytes];  NSLog(@"range %@", range);  [objc] view%20plain copy 分段下载文件  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:kTimeout];  NSString *range = [NSString stringWithFormat:@"bytes=%lld-%lld", from, end];  [request setValue:range forHTTPHeaderField:@"Range"];    NSURLResponse *response = nil;  NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];        NSLog(@"%@-%@-%ld", range, response, (unsigned long)data.length);  提示:  如果GET包含Range请求头,响应会以状态码206(PartialContent)返回而不是200(OK)  [objc] view%20plain copy 将数据写入文件  // 打开缓存文件  NSFileHandle *fp = [NSFileHandle fileHandleForWritingAtPath:self.cachePath];  // 如果文件不存在,直接写入数据  if (!fp) {      [data writeToFile:self.cachePath atomically:YES];  } else {      // 移动到文件末尾      [fp seekToEndOfFile];      // 将数据文件追加到文件末尾      [fp writeData:data];      // 关闭文件句柄      [fp closeFile];  }  [objc] view%20plain copy 检查文件大小  // 判断文件是否存在  if ([[NSFileManager defaultManager] fileExistsAtPath:self.cachePath]) {      NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:self.cachePath error:NULL];      return [dict[NSFileSize] longLongValue];  } else {      return 0;  }    提示:由于数据是追加的,为了避免重复从网络下载文件,在下载之前  判断缓存路径中文件是否已经存在  如果存在检查文件大小  如果文件大小与网络资源大小一致,则不再下载  全部代码如下

[objc] view%20plain copy //  //  MJViewController.m  //  01.文件下载  //  //  Created by apple on 14-4-29.  //  Copyright (c) 2014年 itcast. All rights reserved.  //    #import "MJViewController.h"  #import "FileDownload.h"    @interface MJViewController ()  @PRoperty (nonatomic, strong) FileDownload *download;  @property (weak, nonatomic) IBOutlet UIImageView *imageView;  @end    @implementation MJViewController    - (void)viewDidLoad  {      [super viewDidLoad];            self.download = [[FileDownload alloc] init];      [self.download downloadFileWithURL:[NSURL URLWithString:@"http://localhost/itcast/images/head4.png"] completion:^(UIImage *image) {                    self.imageView.image = image;      }];  }    @end  [objc] view plain copy 在CODE上查看代码片//  //  FileDownload.m  //  01.文件下载  //  //  Created by apple on 14-4-29.  //  Copyright (c) 2014年 itcast. All rights reserved.  //    #import "FileDownload.h"  #import "NSString+PassWord.h"    #define kTimeOut        2.0f  // 每次下载的字节数  #define kBytesPerTimes  20250    @interface FileDownload()  @property (nonatomic, strong) NSString *cacheFile;  @property (nonatomic, strong) UIImage *cacheImage;  @end    @implementation FileDownload  /**  为了保证开发的简单,所有方法都不使用多线程,所有的注意力都保持在文件下载上    在开发中如果碰到比较绕的计算问题时,建议:  1> 测试数据不要太大  2> 测试数据的数值变化,能够用笔算计算出准确的数值  3> 编写代码对照测试   */  //- (NSString *)cacheFile  //{  //    if (!_cacheFile) {  //        NSString *cacheDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];  //        _cacheFile = [cacheDir stringByAppendingPathComponent:@"123.png"];  //    }  //    return _cacheFile;  //}  - (UIImage *)cacheImage  {      if (!_cacheImage) {          _cacheImage = [UIImage imageWithContentsOfFile:self.cacheFile];      }      return _cacheImage;  }    - (void)setCacheFile:(NSString *)urlStr  {      NSString *cacheDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];      urlStr = [urlStr md5];            _cacheFile = [cacheDir stringByAppendingPathComponent:urlStr];  }    - (void)downloadFileWithURL:(NSURL *)url completion:(void (^)(UIImage *image))completion  {      // GCD中的串行队列异步方法      dispatch_queue_t q = dispatch_queue_create("cn.itcast.download", DISPATCH_QUEUE_SERIAL);            dispatch_async(q, ^{          NSLog(@"%@", [NSThread currentThread]);                    // 把对URL进行MD5加密之后的结果当成文件名          self.cacheFile = [url absoluteString];                    // 1. 从网络下载文件,需要知道这个文件的大小          long long fileSize = [self fileSizeWithURL:url];          // 计算本地缓存文件大小          long long cacheFileSize = [self localFileSize];                    if (cacheFileSize == fileSize) {              dispatch_async(dispatch_get_main_queue(), ^{                  completion(self.cacheImage);              });              NSLog(@"文件已经存在");              return;          }                    // 2. 确定每个数据包的大小          long long fromB = 0;          long long toB = 0;          // 计算起始和结束的字节数          while (fileSize > kBytesPerTimes) {              // 20480 + 20480              //              toB = fromB + kBytesPerTimes - 1;                            // 3. 分段下载文件              [self downloadDataWithURL:url fromB:fromB toB:toB];                            fileSize -= kBytesPerTimes;              fromB += kBytesPerTimes;          }          [self downloadDataWithURL:url fromB:fromB toB:fromB + fileSize - 1];            dispatch_async(dispatch_get_main_queue(), ^{              completion(self.cacheImage);          });              });  }    #pragma mark 下载指定字节范围的数据包  /**  NSURLRequestUseProtocolCachePolicy = 0,        // 默认的缓存策略,内存缓存    NSURLRequestReloadIgnoringLocalCacheData = 1,  // 忽略本地的内存缓存  NSURLRequestReloadIgnoringCacheData  */  - (void)downloadDataWithURL:(NSURL *)url fromB:(long long)fromB toB:(long long)toB  {      NSLog(@"数据包:%@", [NSThread currentThread]);            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:kTimeOut];            // 指定请求中所要GET的字节范围      NSString *range = [NSString stringWithFormat:@"Bytes=%lld-%lld", fromB, toB];      [request setValue:range forHTTPHeaderField:@"Range"];      NSLog(@"%@", range);            NSURLResponse *response = nil;      NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];            // 写入文件,覆盖文件不会追加  //    [data writeToFile:@"/Users/aplle/Desktop/1.png" atomically:YES];      [self appendData:data];            NSLog(@"%@", response);  }    #pragma mark - 读取本地缓存文件大小  - (long long)localFileSize  {      // 读取本地文件信息      NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:self.cacheFile error:NULL];      NSLog(@"%lld", [dict[NSFileSize] longLongValue]);            return [dict[NSFileSize] longLongValue];  }    #pragma mark - 追加数据到文件  - (void)appendData:(NSData *)data  {      // 判断文件是否存在      NSFileHandle *fp = [NSFileHandle fileHandleForWritingAtPath:self.cacheFile];      // 如果文件不存在创建文件      if (!fp) {          [data writeToFile:self.cacheFile atomically:YES];      } else {          // 如果文件已经存在追加文件          // 1> 移动到文件末尾          [fp seekToEndOfFile];          // 2> 追加数据          [fp writeData:data];          // 3> 写入文件          [fp closeFile];      }  }    #pragma mark - 获取网络文件大小  - (long long)fileSizeWithURL:(NSURL *)url  {      // 默认是GET      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:kTimeOut];            // HEAD 头,只是返回文件资源的信息,不返回具体是数据      // 如果要获取资源的MIMEType,也必须用HEAD,否则,数据会被重复下载两次      request.HTTPMethod = @"HEAD";        // 使用同步方法获取文件大小      NSURLResponse *response = nil;            [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];            // expectedContentLength文件在网络上的大小      NSLog(@"%lld", response.expectedContentLength);            return response.expectedContentLength;  }    @end  

二、文件上传

代码如下

[objc] view plain copy 在CODE上查看代码片//  //  MJViewController.m  //  02.Post上传  //  //  Created by apple on 14-4-29.  //  Copyright (c) 2014年 itcast. All rights reserved.  //    #import "MJViewController.h"  #import "UploadFile.h"    @interface MJViewController ()    @end    @implementation MJViewController    - (void)viewDidLoad  {      [super viewDidLoad];        UploadFile *upload = [[UploadFile alloc] init];            NSString *urlString = @"http://localhost/upload.php";            NSString *path = [[NSBundle mainBundle] pathForResource:@"头像1.png" ofType:nil];      NSData *data = [NSData dataWithContentsOfFile:path];            [upload uploadFileWithURL:[NSURL URLWithString:urlString] data:data];  }    @end  [objc] view plain copy 在CODE上查看代码片//  //  UploadFile.m  //  02.Post上传  //  //  Created by apple on 14-4-29.  //  Copyright (c) 2014年 itcast. All rights reserved.  //    #import "UploadFile.h"    @implementation UploadFile  // 拼接字符串  static NSString *boundaryStr = @"--";   // 分隔字符串  static NSString *randomIDStr;           // 本次上传标示字符串  static NSString *uploadID;              // 上传(php)脚本中,接收文件字段    - (instancetype)init  {      self = [super init];      if (self) {          randomIDStr = @"itcast";          uploadID = @"uploadFile";      }      return self;  }    #pragma mark - 私有方法  - (NSString *)topStringWithMimeType:(NSString *)mimeType uploadFile:(NSString *)uploadFile  {      NSMutableString *strM = [NSMutableString string];            [strM appendFormat:@"%@%@/n", boundaryStr, randomIDStr];      [strM appendFormat:@"Content-Disposition: form-data; name=/"%@/"; filename=/"%@/"/n", uploadID, uploadFile];      [strM appendFormat:@"Content-Type: %@/n/n", mimeType];            NSLog(@"%@", strM);      return [strM copy];  }    - (NSString *)bottomString  {      NSMutableString *strM = [NSMutableString string];            [strM appendFormat:@"%@%@/n", boundaryStr, randomIDStr];      [strM appendString:@"Content-Disposition: form-data; name=/"submit/"/n/n"];      [strM appendString:@"Submit/n"];      [strM appendFormat:@"%@%@--/n", boundaryStr, randomIDStr];            NSLog(@"%@", strM);      return [strM copy];  }    #pragma mark - 上传文件  - (void)uploadFileWithURL:(NSURL *)url data:(NSData *)data  {      // 1> 数据体      NSString *topStr = [self topStringWithMimeType:@"image/png" uploadFile:@"头像1.png"];      NSString *bottomStr = [self bottomString];            NSMutableData *dataM = [NSMutableData data];      [dataM appendData:[topStr dataUsingEncoding:NSUTF8StringEncoding]];      [dataM appendData:data];      [dataM appendData:[bottomStr dataUsingEncoding:NSUTF8StringEncoding]];            // 1. Request      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:2.0f];            // dataM出了作用域就会被释放,因此不用copy      request.HTTPBody = dataM;            // 2> 设置Request的头属性      request.HTTPMethod = @"POST";            // 3> 设置Content-Length      NSString *strLength = [NSString stringWithFormat:@"%ld", (long)dataM.length];      [request setValue:strLength forHTTPHeaderField:@"Content-Length"];            // 4> 设置Content-Type      NSString *strContentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", randomIDStr];      [request setValue:strContentType forHTTPHeaderField:@"Content-Type"];            // 3> 连接服务器发送请求      [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {                    NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];          NSLog(@"%@", result);      }];  }        @end  
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表