IOS如何根据URL下载内容

In order to download the contents of a URL, an application needs to provide a delegate object that, at a minimum, implements the following delegate methods: connection:didReceiveResponse:, connection:didReceiveData:, connection:didFailWithError: and connectionDidFinishLoading:.

为了根据URL下载对应的内容,程序需要提供一个delegate对象,该delegate对象至少需要来实现这些方法:

connection:didReceiveResponse:, connection:didReceiveData:, connection:didFailWithError: and connectionDidFinishLoading:.

Listing1的例子对一个connection的URL进行了初始化。它首先给URL创建一个NSURLRequest实例,并且给连接connection指定缓存获取策略以及timeout间隔。然后给请求新建一个NSURLConnection实例theConnection,并初始化NSURLConnection实例,即指定一个请求request,以及delegate。如果不能给请求创建theConnection或者初始化请求delegate失败,就返回nil对象。如果创建成功,那么就创建一个NSMutableData实例来保存从网络上下载的数据。

The example in Listing 1 initiates a connection for a URL. It begins by creating an NSURLRequest instance for the URL, specifying the cache access policy and the timeout interval for the connection. It then creates an NSURLConnection instance, specifying the request and a delegate. If NSURLConnection can’t create a connection for the request, initWithRequest:delegate: returns nil. If the connection is successful, an instance of NSMutableData is created to store the data that is provided to the delegate incrementally.
Listing 1的代码如下:
Listing 1  Creating a connection using NSURLConnection
// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/"]
                        cachePolicy:NSURLRequestUseProtocolCachePolicy
                    timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
    // Create the NSMutableData to hold the received data.
    // receivedData is an instance variable declared elsewhere.
    receivedData = [[NSMutableData data] retain];
} else {
    // Inform the user that the connection failed.
}

当接收到initWithRequest:delegate:消息后,下载就开始了。当委托接受到connectionDidFinishLoading: 下载结束,或者接受connection:didFailWithError:消息,给connection发送cancel消息是,下载也结束。

The download starts immediately upon receiving the initWithRequest:delegate: message. It can be canceled any time before the delegate receives a connectionDidFinishLoading: or connection:didFailWithError: message by sending the connection a cancel message.

当服务器提供足够的数据来创建NSURLResponse对象时,委托将收到一个connection:didReceiveResponse:消息。委托将调用connection:didReceiveResponse:方法。在该方法中检查提供的NSURLResponse对象以及服务器提供的决定将接收数据的长度、MIME类型、推荐的文件名以及其他的元数据。
When the server has provided sufficient data to create an NSURLResponse object, the delegate receives a connection:didReceiveResponse: message. The delegate method can examine the provided NSURLResponse and determine the expected content length of the data, MIME type, suggested filename and other metadata provided by the server.
你可以对委托设置对于一个单连接的接收connection:didReceiveResponse:消息的次数。这种消息大部分是因为服务器的重定向引起的,也可能是MIME文件的多个不同部分导致的。每一次委托接收到connection:didReceiveResponse:消息都会重新设定所有的进度指示以及丢弃前面接收到的数据。在Listing 2中完成当connection:didReceiveResponse:每次调用时重设接收数据的长度的例子。
You should be prepared for your delegate to receive the connection:didReceiveResponse: message multiple times for a single connection. This message can be sent due to server redirects, or in rare cases multi-part MIME documents. Each time the delegate receives the connection:didReceiveResponse: message, it should reset any progress indication and discard all previously received data. The example implementation in Listing 2 simply resets the length of the received data to 0 each time it is called.

Listing 2  Example connection:didReceiveResponse: implementation
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // This method is called when the server has determined that it
    // has enough information to create the NSURLResponse.
 
    // It can be called multiple times, for example in the case of a
    // redirect, so each time we reset the data.
 
    // receivedData is an instance variable declared elsewhere.
    [receivedData setLength:0];

}

同时当接收到了数据时,委托将会周期性的收到connection:didReceiveData:消息。委托有责任存储新接收到的数据。Listing 3完成的就是委托接收到了connection:didReceiveData:消息完成的操作。

The delegate is periodically sent connection:didReceiveData: messages as the data is received. The delegate implementation is responsible for storing the newly received data. In the example implementation in Listing 3, the new data is appended to the NSMutableData object created in Listing 1.

Listing 3  Example connection:didReceiveData: implementation
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // Append the new data to receivedData.
    // receivedData is an instance variable declared elsewhere.
    [receivedData appendData:data];
}
You can also use the connection:didReceiveData: method to provide an indication of the connection’s progress to the user.

如果在下载过程中遇到了错误,委托将收到connection:didFailWithError: message消息。而且NSError对象将会作为参数来指定具体的错误。还可以根据键值NSURLErrorFailingURLStringErrorKey从error info字典查出具体的错误提供给请求的URL。

If an error is encountered during the download, the delegate receives a connection:didFailWithError: message. The NSError object passed as the parameter specifies the details of the error. It also provides the URL of the request that failed in the user info dictionary using the key NSURLErrorFailingURLStringErrorKey.

当委托接收到了connection:didFailWithError:消息后,它将不在接收该连接的任何委托消息了。
After the delegate receives a message connection:didFailWithError:, it receives no further delegate messages for the specified connection.

The example in Listing 4 releases the connection, as well as any received data, and logs the error.

Listing 4  Example connectionDidFailWithError: implementation
- (void)connection:(NSURLConnection *)connection
  didFailWithError:(NSError *)error
{
    // release the connection, and the data object
    [connection release];
    // receivedData is declared as a method instance elsewhere
    [receivedData release];
 
    // inform the user
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);

}

最后,当连接成功的根据请求下载完成时,委托将收到connectionDidFinishLoading: message消息。委托将不再接收该连接的请求,而且需要释放NSURLConnection对象

Finally, if the connection succeeds in downloading the request, the delegate receives the connectionDidFinishLoading: message. The delegate will receive no further messages for the connection and the NSURLConnection object can be released.
Listing 5完成了当下载数据结束时的代码。
The example implementation in Listing 5 logs the length of the received data and releases both the connection object and the received data.

Listing 5  Example connectionDidFinishLoading: implementation
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // do something with the data
    // receivedData is declared as a method instance elsewhere
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
 
    // release the connection, and the data object
    [connection release];
    [receivedData release];

}

上面使用NSURLConnection实现了简单的一个客户端。额外的委托方法提供自定义处理服务器重定向、请求认证、缓存响应的能力。

This represents the simplest implementation of a client using NSURLConnection. Additional delegate methods provide the ability to customize the handling of server redirects, authorization requests and caching of the response.

控制响应缓存Controlling Response Caching
在默认情况下,根据NSURLProtocol的子类提供的功能能够支持一个连接的数据缓存。NSURLConnection通过实现connection:willCacheResponse:方法能够进一步限定该行为。
By default the data for a connection is cached according to the support provided by the NSURLProtocol subclass that handles the request. An NSURLConnection delegate can further refine that behavior by implementing connection:willCacheResponse:.
该委托方法能够检查NSCachedURLResponse对象以及改变响应如何缓存,例如限制内存存储大小或者阻止它们缓存在一起。它也可以将对象插入到NSCachedURLResponse的使用信息字典中,将他们作为响应的一部分存储。
This delegate method can examine the provided NSCachedURLResponse object and change how the response is cached, for example restricting its storage to memory only or preventing it from being cached altogether. It is also possible to insert objects in an NSCachedURLResponse’s user info dictionary, causing them to be stored in the cache as part of the response.

Note: The delegate receives connection:willCacheResponse: messages only for protocols that support caching.
The example in Listing 6 prevents the caching of https responses. It also adds the current date to the user info dictionary for responses that are cached.

Listing 6  Example connection:withCacheResponse: implementation
-(NSCachedURLResponse *)connection:(NSURLConnection *)connection
                 willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
    NSCachedURLResponse *newCachedResponse = cachedResponse;
 
    if ([[[[cachedResponse response] URL] scheme] isEqual:@"https"]) {
        newCachedResponse = nil;
    } else {
        NSDictionary *newUserInfo;
        newUserInfo = [NSDictionary dictionaryWithObject:[NSCalendarDate date]
                                                 forKey:@"Cached Date"];
        newCachedResponse = [[[NSCachedURLResponse alloc]
                                initWithResponse:[cachedResponse response]
                                    data:[cachedResponse data]
                                    userInfo:newUserInfo
                                    storagePolicy:[cachedResponse storagePolicy]]
                            autorelease];
    }
    return newCachedResponse;
}

估计上传的进度

Estimating Upload Progress

你也可以用委托方法connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:来估计一个HTTP POST方法的进度。注意这个不是准确的来测量上传进度的方法,因为connection可能会出现fail或者遇到验证的问题。
You can estimate the progress of an HTTP POST upload with the connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite: delegate method. Note that this is not an exact measurement of upload progress, because the connection may fail or the connection may encounter an authentication challenge.

同步下载数据

Downloading Data Synchronously

NSURLConnection使用sendSynchronousRequest:returningResponse:error:方法能够采用同步的方式来下载NSURLRequest的内容,但是一般不推荐。因为存在这严重的缺陷。
NSURLConnection provides support for downloading the contents of an NSURLRequest in a synchronous manner using the class method sendSynchronousRequest:returningResponse:error:. Using this method is not recommended, because it has severe limitations:
客户端可能会阻塞直到下面的三种情况出现:1.完全接收了数据;2.遇到了错误;3.请求time out
The client application blocks until the data has been completely received, an error is encountered, or the request times out.

但是同步下载的好处是当请求需要验证时。

Minimal support is provided for requests that require authentication.

调整缓存响应或者接收服务器的重定向的默认行为是没有多少作用的。

There is no means of modifying the default behavior of response caching or accepting server redirects.
If the download succeeds, the contents of the request are returned as an NSData object and an NSURLResponse for the request is returned by reference. If NSURLConnection is unable to download the URL, the method returns nil and any available NSError instance by reference in the appropriate parameter.

If the request requires authentication in order to make the connection, valid credentials must already be available in the NSURLCredentialStorage, or must be provided as part of the requested URL. If the credentials are not available or fail to authenticate, the URL loading system responds by sending the NSURLProtocol subclass handling the connection a continueWithoutCredentialForAuthenticationChallenge: message.

When a synchronous connection attempt encounters a server redirect, the redirect is always honored. Likewise the response data is stored in the cache according to the default support provided by the protocol implementation
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值