IOS development-basic implementation of the download tool function, ios development download Tool
Today, we made a Demo of the download tool, that is, to download the specified file from the locally configured Apache server. This time, we download the html.mp4 file under the server root directory.
By convention, we first create a URL object and request.
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/html.mp4"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
There are two points to note: first, the url string is in full English. If Chinese characters appear in the string, we cannot directly call URLWithString: This method, instead, you need to first store the url string into a string object, and then pass the string through
[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
Method. Otherwise, the request fails.
Because it is a download operation, we need to use the NSURLConnection proxy method for implementation, the premise is to first create a connection object and object proxy.
// Establish a connection and immediately execute [NSURLConnection connectionWithRequest: request delegate: self];
Now the problem arises. The proxy is more than one option. <NSURLConnectionDownloadDelegate> and <NSURLConnectionDataDelegate> instinctively choose the first proxy for first contact (because the first most image is from the name ). If you think the same way as me, it will be wrong. After the method in the first proxy is implemented, the data can be obtained, but you do not know where the data exists, it is not the path we specified. You can try it.
Well, after the first failure, we chose the second proxy to go To the header file. We saw four methods:
// Get response
-(void) connection: (NSURLConnection *) connection didReceiveResponse: (NSURLResponse *) response;
//retrieve data
-(void) connection: (NSURLConnection *) connection didReceiveData: (NSData *) data;
//Disconnect
-(void) connectionDidFinishLoading: (NSURLConnection *) connection;
//An error occurred
-(void) connection: (NSURLConnection *) connection didFailWithError: (NSError *) error;
We can clearly understand the role of each method. If you are interested, you can print the parameters of each method.
Here, we need to add several attributes.
/// file download stream
@property (strong, nonatomic) NSOutputStream * fileStream;
/// Record file total length
@property (assign, nonatomic) long long fileLength;
/// The current length of the file
@property (assign, nonatomic) long long currentFileLength;
For NSOutputStream, there is also an NSFileHandle that can be compared with it, but the latter will cause repeated append of the file. Therefore, we should select the former. According to the class name, we can infer that there should be an NSInputStream. That's right, a download stream and an upload stream.
Step 1. In the response method, we get the total length of the file from the response parameter, and set the length of the downloaded file to 0. Open a download stream saved to the specified path, save it to the desktop.
// Get response
-(void) connection: (NSURLConnection *) connection didReceiveResponse: (NSURLResponse *) response
{
self.fileLength = response.expectedContentLength;
// zero the current file length
self.currentFileLength = 0;
self.fileStream = [[NSOutputStream alloc] initToFileAtPath: @ "/ Users / xxx / Desktop / html.mp4" append: YES];
[self.fileStream open];
}
Step 2. We have obtained the data. If you print the data in this method, you will find that when the file is large enough (a few MB), this method will be called multiple times, that is, obtain data multiple times. Therefore, we need to splice data in this method and avoid occupying too much memory after splicing data. We accumulate the length of downloaded data, calculate the percentage of downloaded data, and write it into the data stream. When calculating the percentage, remember to convert the type. Otherwise, the result is 0, except that the last one is 1.
//retrieve data
-(void) connection: (NSURLConnection *) connection didReceiveData: (NSData *) data
{
// NSLog (@ "did receive:% @", data);
self.currentFileLength + = data.length;
float progressPercent = (float) self.currentFileLength / self.fileLength;
NSLog (@ "have downloaded:% f", progressPercent);
[self.fileStream write: data.bytes maxLength: data.length];
}
The last step. There are actually two methods: one is the download completion call and the other is the download failure call. Note that the file output stream must be closed no matter whether the download is successful or fails.
//Disconnect
-(void) connectionDidFinishLoading: (NSURLConnection *) connection
{
NSLog (@ "End of connection");
[self.fileStream close];
}
//An error occurred
-(void) connection: (NSURLConnection *) connection didFailWithError: (NSError *) error
{
NSLog (@ "% @", error);
[self.fileStream close];
}
This is only the basic implementation of the download function. Next we will add a download progress bar, optimize the download operations (multithreading, resumable upload, etc.), and encapsulate the download operations.
Thank you for reading!