Note: File uploads are used when post requests, usually to upload data stored in the request body. This article describes how to implement the file upload in iOS development without the help of a third party framework.
Because of the complexity of the process, only some of the key code is posted in this article.
Supplementary Note: File upload request data format
MimeType of some files
Multi-threaded Breakpoint Download
Description: This article describes multithreaded breakpoint downloads. The project uses the Apple-band class, which enables simultaneous opening of multiple threads to download a larger file. Because the implementation process is more complex, the complete code is posted below.
Realization: Download begins, create a file that is the same size as the file you want to download (if the file you want to download is 100M, create a 100M file in the sandbox, and then calculate the download amount for each segment, open multiple threads to download the data for each segment, and write the corresponding file section separately).
The main classes used in the project are as follows:
The completed implementation code is as follows:
Code in the primary controller:
Copy Code code as follows:
#import "YYViewController.h"
#import "YYFileMultiDownloader.h"
@interface Yyviewcontroller ()
@property (nonatomic, strong) Yyfilemultidownloader *filemultidownloader;
@end
Copy Code code as follows:
@implementation Yyviewcontroller
-(Yyfilemultidownloader *) Filemultidownloader
{
if (!_filemultidownloader) {
_filemultidownloader = [[Yyfilemultidownloader alloc] init];
File remote URL that needs to be downloaded
_filemultidownloader.url = @ "Http://192.168.1.200:8080/MJServer/resources/jre.zip";
Where is the file saved?
NSString *caches = [Nssearchpathfordirectoriesindomains (nscachesdirectory, Nsuserdomainmask, YES) lastObject];
NSString *filepath = [Caches stringbyappendingpathcomponent:@ "Jre.zip"];
_filemultidownloader.destpath = filepath;
}
return _filemultidownloader;
}
-(void) viewdidload
{
[Super Viewdidload];
}
-(void) Touchesbegan: (Nsset *) touches withevent: (Uievent *) event
{
[Self.filemultidownloader start];
}
@end
Customizing a base class
Copy Code code as follows:
YYFileDownloader.h file
#import <Foundation/Foundation.h>
@interface Yyfiledownloader:nsobject
{
BOOL _downloading;
}
/**
* The remote URL of the required download file (the path to connect to the server)
*/
@property (nonatomic, copy) NSString *url;
/**
* The storage path of the file (where the file is downloaded)
*/
@property (nonatomic, copy) NSString *destpath;
/**
* is downloading (there is no download, only the inside of the download to know)
*/
@property (Nonatomic, readonly, getter = isdownloading) BOOL downloading;
/**
* Used to monitor download progress
*/
@property (nonatomic, copy) void (^progresshandler) (double progress);
/**
* Start (Resume) Download
*/
-(void) start;
/**
* Suspend download
*/
-(void) pause;
@end
YYFILEDOWNLOADER.M file
Copy Code code as follows:
#import "YYFileDownloader.h"
@implementation Yyfiledownloader
@end
The download class inherits from the Yyfiledownloader class YYFileSingDownloader.h file
Copy Code code as follows:
#import "YYFileDownloader.h"
@interface Yyfilesingledownloader:yyfiledownloader
/**
* Where to start
*/
@property (nonatomic, assign) long long begin;
/**
* End of position
*/
@property (nonatomic, assign) long long end;
@end
YYFILESINGDOWNLOADER.M file
Copy Code code as follows:
#import "YYFileSingleDownloader.h"
@interface Yyfilesingledownloader () <NSURLConnectionDataDelegate>
/**
* Connection Object
*/
@property (nonatomic, strong) nsurlconnection *conn;
/**
* File handle for writing data
*/
@property (nonatomic, strong) Nsfilehandle *writehandle;
/**
* The length of the currently downloaded data
*/
@property (nonatomic, assign) long long currentlength;
@end
Copy Code code as follows:
@implementation Yyfilesingledownloader
-(Nsfilehandle *) writehandle
{
if (!_writehandle) {
_writehandle = [Nsfilehandle FileHandleForWritingAtPath:self.destPath];
}
return _writehandle;
}
/**
* Start (Resume) Download
*/
-(void) Start
{
Nsurl *url = [Nsurl URLWithString:self.url];
The default is GET request
Nsmutableurlrequest *request = [Nsmutableurlrequest Requestwithurl:url];
Set Request header information
NSString *value = [NSString stringwithformat:@ "Bytes=%lld-%lld", Self.begin + self.currentlength, self.end];
[Request Setvalue:value forhttpheaderfield:@ "Range"];
Self.conn = [nsurlconnection connectionwithrequest:request delegate:self];
_downloading = YES;
}
/**
* Suspend download
*/
-(void) Pause
{
[Self.conn Cancel];
Self.conn = nil;
_downloading = NO;
}
#pragma mark-nsurlconnectiondatadelegate proxy method
/**
* 1. The
*/is invoked when the response to the server (connected to the server) is received
-(void) connection: (Nsurlconnection *) connection didreceiveresponse: (nsurlresponse *) response
{
}
/**
* 2. The data that is received to the server is invoked (may be invoked multiple times, and only partial data is passed each time)
*/
-(void) connection: ( Nsurlconnection *) connection didreceivedata: (NSData *) data
{
//move to Tail of file
& nbsp [Self.writehandle SeekToFileOffset:self.begin + self.currentlength];
/Start writing data from the currently moving location (end of file)
[Self.writehandle writedata:data];
& nbsp;
//Cumulative length
self.currentlength + = data.length;
& nbsp
//Print download Progress
Double progress = (double) self.currentlength/(self.end-self.b Egin);
if (self.progresshandler) {
Self.progresshandler (progress);
}
}
/**
* 3. When the server's data is accepted, it is called
*/
-(void) connectiondidfinishloading: (nsurlconnection *) connection
{
Empty property values
self.currentlength = 0;
Close the connection (no more data is entered into the file)
[Self.writehandle CloseFile];
Self.writehandle = nil;
}
/**
* Request error (failure) when called (Request timeout \ Disconnected network \ No network, generally refers to client error)
*/
-(void) connection: (Nsurlconnection *) connection didfailwitherror: (Nserror *) error
{
}
@end
Design multi-threaded Downloader (use Hmfilemultidownloader to open multiple threads and download a file simultaneously) A multithreaded downloader downloads only one file
YYFileMultiDownloader.h file
Copy Code code as follows:
#import "YYFileDownloader.h"
@interface Yyfilemultidownloader:yyfiledownloader
@end
YYFILEMULTIDOWNLOADER.M file
Copy Code code as follows:
#import "YYFileMultiDownloader.h"
#import "YYFileSingleDownloader.h"
#define YYMAXDOWNLOADCOUNT 4
@interface Yyfilemultidownloader ()
@property (nonatomic, strong) Nsmutablearray *singledownloaders;
@property (nonatomic, assign) long long totallength;
@end
Copy Code code as follows:
@implementation Yyfilemultidownloader
-(void) getfilesize
{
Nsmutableurlrequest *request = [nsmutableurlrequest requestwithurl:[nsurl URLWithString:self.url]];
Request. HttpMethod = @ "Head";
Nsurlresponse *response = nil;
#warning here to use the asynchronous request
[Nsurlconnection sendsynchronousrequest:request returningresponse:&response Error:nil];
Self.totallength = Response.expectedcontentlength;
}
-(Nsmutablearray *) singledownloaders
{
if (!_singledownloaders) {
_singledownloaders = [Nsmutablearray array];
Get File size
[Self getfilesize];
The amount of downloads per path
Long long size = 0;
if (self.totallength% Yymaxdownloadcount = = 0) {
size = Self.totallength/yymaxdownloadcount;
} else {
Size = Self.totallength/yymaxdownloadcount + 1;
}
Create an n-download device
for (int i = 0; i<yymaxdownloadcount; i++) {
Yyfilesingledownloader *singledownloader = [[Yyfilesingledownloader alloc] init];
Singledownloader.url = Self.url;
Singledownloader.destpath = Self.destpath;
Singledownloader.begin = i * size;
Singledownloader.end = Singledownloader.begin + size-1;
Singledownloader.progresshandler = ^ (double progress) {
NSLog (@ "%d---%f", I, progress);
};
[_singledownloaders Addobject:singledownloader];
}
Create a temporary file that is as large as the server file
[[Nsfilemanager Defaultmanager] CreateFileAtPath:self.destPath contents:nil Attributes:nil];
Let the length of the Self.destpath file be self.totallengt
Nsfilehandle *handle = [Nsfilehandle FileHandleForWritingAtPath:self.destPath];
[Handle truncateFileAtOffset:self.totalLength];
}
return _singledownloaders;
}
/**
* Start (Resume) Download
*/
-(void) Start
{
[Self.singledownloaders makeobjectsperformselector: @selector (start)];
_downloading = YES;
}
/**
* Suspend download
*/
-(void) Pause
{
[Self.singledownloaders makeobjectsperformselector: @selector (pause)];
_downloading = NO;
}
@end
Supplemental Instructions: How do I get the size of the file that will be downloaded?