Ios file upload and post data
I. File Download
There are two methods to obtain the resource file size:
1,
Http head method 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) ;}]; when running the test code, you can find that the HEAD method only returns resource information, but does not return data body application scenarios: gets the resource Mimetype and obtains the resource file size, which is used for resumable data transfer or multi-thread download at the endpoint.
2
How to Use block code to obtain the size of network resources-(void) fileSizeWithURL :( NSURL *) url completion :( void (^) (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 );}
Determine the pseudo-code implementation of each downloaded Packet
-(Void) downloadFileWithURL :( NSURL *) url {[self fileSizeWithURL: url completion: ^ (long contentLength) {NSLog (@ "total file size: % lld", contentLength ); // download the file by size while (contentLength> kDownloadBytes) {NSLog (@ "length of each download: % lld", (long) kDownloadBytes); contentLength-= kDownloadBytes ;} NSLog (@ "last downloaded Bytes: % lld", contentLength) ;}] ;}
HTTP Range example
You can set the Range to specify the size of each packet downloaded from the network.
Range example
Bytes = 0-499 the first 499 bytes from 0 to 500
Bytes = 500-999 the second 500 bytes from 999 to 500
Bytes = 500-All bytes after 500 bytes
Bytes =-500 last 500 bytes
Bytes = 500-599,800-899 specify several ranges at the same time
Range Summary
-Used to separate
The preceding number indicates the number of start bytes.
The array below indicates the number of byte cutoff, not at the end
Used for grouping. You can specify multiple ranges at a time, but it is rarely used.
Implement long fromBytes = 0; 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 );
Multipart download file upload * request = [NSMutableURLRequest requestWithURL: url cachePolicy: Invalid 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); prompt: If GET contains the Range request header, the response will be returned with the status code 206 (PartialContent) instead of 200 (OK)
Write data to a file // open the cached file NSFileHandle * fp = [NSFileHandle fileHandleForWritingAtPath: self. cachePath]; // if the file does not exist, directly write data if (! Fp) {[data writeToFile: self. cachePath atomically: YES];} else {// move to the end of the file [fp seekToEndOfFile]; // append the data file to the end of the file [fp writeData: data]; // close the file handle [fp closeFile];}
Check the file size // determine whether the file exists if ([[NSFileManager defaultManager] fileExistsAtPath: self. cachePath]) {NSDictionary * dict = [[NSFileManager defaultManager] attributesOfItemAtPath: self. cachePath error: NULL]; return [dict [NSFileSize] longLongValue];} else {return 0;} prompt: because the data is appended, in order to avoid repeated download from the network, before downloading, check whether the file in the cache path already exists. If yes, check the file size. If the file size is the same as the network resource size, the file will not be downloaded.
The Code is as follows:
/// MJViewController. m // 01. file Download /// 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
//// FileDownload. m // 01. file Download /// 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 // number of bytes downloaded each time # define kBytesPerTimes 20250 @ interface FileDownload () @ property (nonatomic, strong) NSString * cacheFile; @ property (nonatomic, strong) UIImage * cacheImage; @ end @ implementation FileDownload/** all The method does not use multithreading, and all attention is kept on the file download. If you encounter computation problems that are relatively difficult during development, we recommend that you: 1> test data should not be too big 2> test data value changes, can calculate accurate values with a pen 3> write code against test * //-(NSString *) cacheFile // {// if (! _ CacheFile) {// NSString * cacheDir = bytes (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 {// Asynchronous Method of serial queue in GCD dispatch_queue_t q = dispatch_queue_create ("cn. itcast. download ", DISPATCH_QUEUE_SERIAL); dispatch_async (q, ^ {NSLog (@" % @ ", [NSThread currentThread]); // The result of MD5 encryption on the URL is treated as the file name self. cacheFile = [url absoluteString]; // 1. to download a file from the network, you need to know the file size long fileSize = [self fileSizeWithURL: url]; // calculate the local cache file size long cacheFileSize = [self localFileSize]; if (cacheFi LeSize = fileSize) {dispatch_async (dispatch_get_main_queue (), ^ {completion (self. cacheImage) ;}); NSLog (@ "file already exists"); return ;}// 2. determine the size of each data packet long fromB = 0; long toB = 0; // calculate the number of start and end bytes while (fileSize> kBytesPerTimes) {// 20480 + 20480 // toB = fromB + kBytesPerTimes-1; // 3. multipart download file [self downloadDataWithURL: url fromB: fromB toB: toB]; fileSize-= kBytesPerTimes; fromB + = kBytesPe RTimes;} [self downloadDataWithURL: url fromB: fromB toB: fromB + fileSize-1]; dispatch_async (dispatch_get_main_queue (), ^ {completion (self. cacheImage) ;};}) ;}# pragma mark downloads data packets within the specified byte range/** NSURLRequestUseProtocolCachePolicy = 0, // default Cache Policy, memory cache NSURLRequestReloadIgnoringLocalCacheData = 1, // ignore the local memory cache NSURLRequestReloadIgnoringCacheData */-(void) downloadDataWithURL :( NSURL *) url fromB :( long) FromB toB :( long) toB {NSLog (@ "packet: % @", [NSThread currentThread]); NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL: url cachePolicy: expires timeoutInterval: kTimeOut]; // specify the byte range of GET in the request NSString * range = [NSString stringWithFormat: @ "Bytes = % lld-% lld", fromB, toB]; [request setValue: range forHTTPHeaderField: @ "Range"]; NSLog (@ "% @", range); NSURLRespon Se * response = nil; NSData * data = [NSURLConnection sendSynchronousRequest: request returningResponse: & response error: NULL]; // write to the file, overwriting the file will not be appended // [data writeToFile: @ "/Users/aplle/Desktop/1.png" atomically: YES]; [self appendData: data]; NSLog (@" % @ ", response );} # pragma mark-read local cache file size-(long) localFileSize {// read local file information NSDictionary * dict = [[NSFileManager defaultManager] attributesOfItemAtPath: sel F. cacheFile error: NULL]; NSLog (@ "% lld", [dict [NSFileSize] longLongValue]); return [dict [NSFileSize] longLongValue];} # pragma mark-append data to the file-(void) appendData :( NSData *) data {// determine whether the file exists NSFileHandle * fp = [NSFileHandle fileHandleForWritingAtPath: self. cacheFile]; // if the file does not exist, create the file if (! Fp) {[data writeToFile: self. cacheFile atomically: YES];} else {// if the file already exists, move it to the end of the file [fp seekToEndOfFile]; // 2> append data [fp writeData: data]; // 3> write the file [fp closeFile] ;}# pragma mark-get the network file size-(long) fileSizeWithURL :( NSURL *) url {// The default value is GET NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL: url cachePolicy: 0 timeoutInterval: kTimeOut]; // the header of the HEAD, which only returns information about the file resource, no specific data is returned. // if you want to obtain the MIMEType of the resource, you must use the HEAD. Otherwise, the data will be downloaded twice. HTTPMethod = @ "HEAD"; // use the synchronization method to obtain the file size NSURLResponse * response = nil; [NSURLConnection sendSynchronousRequest: request returningResponse: & response error: NULL]; // The size of the expectedContentLength file on the network NSLog (@ "% lld", response. expectedContentLength); return response. expectedContentLength;} @ end
Ii. File Upload
The Code is as follows:
/// MJViewController. m // 02. post upload /// 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: @" header 1.png "ofType: nil]; NSData * data = [NSData dataWithContentsOfFile: path]; [upload uploadFileWithURL: [NSURL URLWithString: urlString] data: data] ;}@ end
//// UploadFile. m // 02. post upload /// Created by apple on 14-4-29. // Copyright (c) 2014 itcast. all rights reserved. // # import "UploadFile. h "@ implementation UploadFile // concatenate the string static NSString * boundaryStr = @" -- "; // separate the string static NSString * randomIDStr; // This upload identifies the string static NSString * uploadID; // In the upload (php) script, the received file field-(instancetype) init {self = [super init]; if (self) {randomIDStr = @ "itcast "; uploadID = @ "uploadFile";} return self ;}# pragma mark-Private method-(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 ", 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 "]; [strM appendString: @" Submit \ n "]; [strM appendFormat: @ "% @ -- \ n", boundaryStr, randomIDStr]; NSLog (@ "% @", strM); return [strM copy];} # pragma mark-Upload File-(void) uploadFileWithURL :( NSURL *) url data :( NSData *) data {// 1> data body NSString * topStr = [self topStringWithMimeType: @ "image/png" uploadFile: @ "header 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]; // If dataM is out of scope, it will be released, so no copy request is required. HTTPBody = dataM; // 2> set the Request header attribute request. HTTPMethod = @ "POST"; // 3> set Content-Length NSString * strLength = [NSString stringWithFormat: @ "% ld", (long) dataM. length]; [request setValue: strLength forHTTPHeaderField: @ "Content-Length"]; // 4> set Content-Type NSString * strContentType = [NSString stringWithFormat: @ "multipart/form-data; boundary = % @", randomIDStr]; [request setValue: strContentType forHTTPHeaderField: @ "Content-Type"]; // 3> connection server sends request [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