zoukankan      html  css  js  c++  java
  • ASIHTTPRequest学习(二)

    • Handling compressed responses, and compressing request bodies

    • Using gzip to handle compressed response data

    Using gzip in ASIHTTPRequest

    - (IBAction)grabURL:(id)sender
    {
      NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
      ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
      // YES is the default, you can turn off gzip compression by setting this to NO
      [request setAllowCompressedResponse:YES];
      [request startSynchronous];
      BOOL *dataWasCompressed = [request isResponseCompressed]; // Was the response gzip compressed?
      NSData *compressedResponse = [request rawResponseData]; // Compressed data
      NSData *uncompressedData = [request responseData]; // Uncompressed data
      NSString *response = [request responseString]; // Uncompressed data as a string
    }
    这里设置allowCompressedResponse为true,ASIHTTPRequest会添加一个Accept-Encoding header到request表明我们接收gzipped类型的数据。如果是压缩的,那么使用responseData or responseString会解压缩数据。也可以调用rawResponseData来获取原始的数据。
    这里因为服务器端有可能给的是zip,这样自动解压缩可能会丢数据,所以可以考虑直接接收数据后自己解压缩。

    On-the-fly inflating of gzipped responses

    By default, ASIHTTPRequest will wait until a request finishes to inflate (uncompress) a gzipped response. By setting a request’s shouldWaitToInflateCompressedResponses property to NO, you can tell ASIHTTPRequest to inflate the data as is comes in. In some circumstances, this may result in a small speed boost, as data can be processed while a request is waiting for more of the response.

    This feature may be especially useful if you need to parse the response with a streaming parser (eg an XML or JSON parser). With this option enabled, you can feed inflated data directly to your parser as it comes in by implementing request:didReceiveData: in your delegate.

    Note that when shouldWaitToInflateCompressedResponses is set to NO, the raw (compressed) data will be discarded. See the comments in ASIHTTPRequest.h for more info.

    Using gzip to compress request bodies

    New in v1.0.3 is gzip compression for request bodies. Using this feature, your applications can compress the content of POST / PUT operations by setting shouldCompressRequestBody to YES. shouldCompressRequestBody is NO by default.

    Apache’s mod_deflate can automatically inflate (decompress) gzipped request bodies when configured with SetInputFilter DEFLATE (More info). This approach works for CGI content, but not when you are using an Apache module built as a RESOURCE filter (such as mod PHP). In these cases, you need to inflate the data yourself.

    ASIHTTPRequest cannot check if a server can accept a gzipped request body or not. Use this feature only if you are certain that the server you are talking to will understand a gzipped body.

    Avoid gzipping content that is in a format that already uses compression (eg JPEG/PNG/GIF/PDF/SWF), you may well find the gzipped version is larger than the original.

    • Resuming interrupted downloads

    - (IBAction)resumeInterruptedDownload:(id)sender
    {
      NSURL *url = [NSURL URLWithString:
        @"http://allseeing-i.com/ASIHTTPRequest/Tests/the_great_american_novel.txt"];
      ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
     
      NSString *downloadPath = @"/Users/ben/Desktop/my_work_in_progress.txt";
     
      // The full file will be moved here if and when the request completes successfully
      [request setDownloadDestinationPath:downloadPath];
     
      // This file has part of the download in it already
      [request setTemporaryFileDownloadPath:@"/Users/ben/Desktop/my_work_in_progress.txt.download"];
      [request setAllowResumeForFileDownloads:YES];
      [request startSynchronous];
     
      //The whole file should be here now.
      NSString *theContent = [NSString stringWithContentsOfFile:downloadPath];
    }
    断点续传功能,需要设置allowResumeForFileDownloadsyes,你必须设置临时的文件路径,因为新的数据会追加到原来的路径中去。然后会移动到downloadDestinationPath当下载完成后。
    Resuming works by reading the size of the file at temporaryFileDownloadPath, and then requesting the rest of the file using a Range: bytes=x HTTP header.

    ASIHTTPRequest does not check for the presence of a Accept-Ranges header (because of the overhead of an additional HEAD request), so only use this feature when you are certain the that server you are connecting to supports partial downloads for the resource you want to download.
    也就是说也要服务器支持断点续传功能才可以。
    • Streaming request bodies directly from disk

    As of v0.96, ASIHTTPRequest can use files on disk as the request body. This means that it is no longer necessary to hold the request body in memory, which should result in a drastic reduction in memory usage for large POST/PUT operations.

    There are several ways you can use this feature:

    ASIFormDataRequests

    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
    [request setPostValue:@"foo" forKey:@"post_var"];
    [request setFile:@"/Users/ben/Desktop/bigfile.txt" forKey:@"file"];
    [request startSynchronous];
     

    ASIFormDataRequests automatically use this feature when you use setFile:forKey:. The request will create a temporary file that will contain the full post body. Files are written a bit at a time to the relevant part of the body. The request is created using CFReadStreamCreateForStreamedHTTPRequest, using a read stream on the file as the source.

    Regular ASIHTTPRequests

    If you know your request is going to be large, turn on streaming from disk on the request:

    [request setShouldStreamPostDataFromDisk:YES];

    In the example below, we add NSData objects to the post body one at a time. There are two methods for doing this - adding data from memory (appendPostData:), or appendPostDataFromFile: to add the contents of a file.

    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setShouldStreamPostDataFromDisk:YES];
    [request appendPostData:myBigNSData];
    [request appendPostDataFromFile:@"/Users/ben/Desktop/bigfile.txt"];
    [request startSynchronous];

    In this example, we want to PUT a large file directly. We set setPostBodyFilePath ourselves, ASIHTTPRequest will use this file as the post body.

    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setRequestMethod:@"PUT"];
    [request setPostBodyFilePath:@"/Users/ben/Desktop/another-big-one.txt"];
    [request setShouldStreamPostDataFromDisk:YES];
    [request startSynchronous];

    IMPORTANT: You should not use setPostBody in the same request as any of the methods described above - they are mutually exclusive. setPostBody should only be used if you want to build the request body yourself, and plan on keeping the request body in memory.

    • Using a download cache

    The API for ASIDownloadCache and ASICacheDelegate has changed in v1.8, and you will need to update your code if you are updating from v1.7.
    In particular, the options available for cache policies are different, and you can now combine multiple cache policies for a single request.

    ASIHTTPRequest can automatically store downloaded data in a cache for use later. This can be helpful in many situations:

    • You want to have access to the data when there is no internet connection and you can’t download it again
    • 想访问数据但是没有网络连接不能再次下载
    • You want to download something only if it has changed since you last downloaded it
    • 只有在数据发生变化后才选择下载
    • The content you are working with will never change, so you only want to download it once
    • 下载的数据只要求下载一次之后不会再改动

    In previous versions of ASIHTTPRequest, handling the above situations would have meant storing the data manually yourself. Using a download cache may eliminate the need for writing any local storage mechanism yourself in some situations.

    ASIDownloadCache is a simple URL cache that can be used for caching the response of GET requests. To be eligible for response caching, requests must succeed (no error), and the server must have returned a 200 OK HTTP response code, or, as of v1.8.1, a 301, 302, 303 and 307 redirect status code.

    Turning on the response cache is easy:

    [ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];

    After you’ve done this, all requests will use the cache automatically. If you prefer, you can set individual requests to use the shared cache on a case by case basis:

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDownloadCache:[ASIDownloadCache sharedCache]];

    You aren’t restricted to a single cache - you can create as many caches as you like. When you create a cache yourself, you must set the storage path for the cache - this should be a folder you have write access to:

     
    ASIDownloadCache *cache = [[[ASIDownloadCache alloc] init] autorelease];
    [cache setStoragePath:@"/Users/ben/Documents/Cached-Downloads"];
     
    // Don't forget - you are responsible for retaining your cache!
    [self setMyCache:cache];
     
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDownloadCache:[self myCache]];

    About cache policies

    Cache policies are the main way you control when information is stored in the cache, and when cached data will be used in preference to downloading the data again.

    The cache policy of individual requests can be controlled using a request’s cachePolicy property. Cache policies are defined using a bitmask, so you can combine multiple options to create the policy you want:

    // Always ask the server if there is new content available, 
    // If the request fails, use data from the cache even if it should have expired.
    [request setCachePolicy:ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy];

    You can use the following options to define a request’s cache policy:

    ASIUseDefaultCachePolicy The default cache policy. When you set a request to use this, it will use the cache’s defaultCachePolicy. ASIDownloadCache’s default cache policy is ‘ASIAskServerIfModifiedWhenStaleCachePolicy’. You should not combine this with other options.
    ASIDoNotReadFromCacheCachePolicy Requests will not read from the cache when using this option.
    ASIDoNotWriteToCacheCachePolicy Requests will not save to the cache when using this option.
    ASIAskServerIfModifiedWhenStaleCachePolicy This is the default cache policy for ASIDownloadCaches. When using this, requests will first look to see if a cached response is available in the cache. If there is no cached data, the request will proceed as normal.
    If there is and the cached data has not expired, the request will use the cached data without contacting the server. If the cached data has expired, the request will perform a conditional GET to see if an updated version is available. If the server says the cached data is current, cached data will be used, and new data will not be downloaded. In this case, the cache’s expiry time will be updated to match the new expiry date from the server. If the server provided updated content, it will be downloaded, and the new data and expiry written to the cache.
    ASIAskServerIfModifiedCachePolicy This is the same as ASIAskServerIfModifiedWhenStaleCachePolicy, except that requests will always ask the server if updated data is available.
    ASIOnlyLoadIfNotCachedCachePolicy When using this option, cached data will always be used if it exists, even if it should have expired.
    ASIDontLoadCachePolicy When using this option, requests will succeed only if a response is already cached. If no response for a request is cached, the request will stop, and no error will be set on the request.
    ASIFallbackToCacheIfLoadFailsCachePolicy When using this option, requests will fallback to cached data if the request fails. If cached data is used after a failure, the request will succeed without error. You would normally use this option in combination with others, as it is only useful for specifying the behaviour to use when something goes wrong.

    When you set the defaultCachePolicy property of a cache, all requests that use that cache will use that cache policy unless they have a custom cache policy set on themselves.

    About storage polices

    Storage policies allow you to define how long a cache will store a particular response. ASIHTTPRequest currently supports two storage policies:

    ASICacheForSessionDurationCacheStoragePolicy is the default. Responses will be stored only for the duration of the session, and will be removed the first time the cache is used, or when [ASIHTTPRequest clearSession] is called.

    With ASICachePermanentlyCacheStoragePolicy, cached responses are stored permanently. To use this storage policy, set it on a request:

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];

    To manually clear the cache, call clearCachedResponsesForStoragePolicy:, passing the storage policy for the cached data you want to remove:

    [[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
    // When you turn shouldRespectCacheControlHeaders off, the cache will store responses even if the server 
    // has explictly asked for them not be be cached (eg with a cache-control or pragma: no-cache header)
    [[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO];
     
    // Set secondsToCache on the request to override any expiry date for the content set by the server, and store 
    // this response in the cache until secondsToCache seconds have elapsed
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setSecondsToCache:60*60*24*30]; // Cache for 30 days
     
    // After a request has run, didUseCachedResponse will return YES if the response was returned from the cache
    [request didUseCachedResponse];
     
    // Ask the cache for a path to store the response. This is the most efficient way to use a download cache, 
    // since data doesn't have to be copied into the cache when the request completes.
    [request setDownloadDestinationPath:
       [[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:request]];
     

    Writing your own cache

    If you already have a download cache and would like to plug it in to ASIHTTPRequest, or you prefer to write your own, have your cache implement the ASICacheDelegate protocol.

    Throttling bandwidth

    As of v1.0.7, ASIHTTPRequest can throttle the bandwidth used by all requests to prevent it going over a user-defined limit. This may help iPhone applications that send or receive large amounts of data to make it through the app store review process.

    Throttling works by using a global limit (in bytes) for how much data can be received or transmitted in one second. All requests share this limit. As they send or receive data, ASIHTTPRequest keeps track of how much data has been sent or received in the last second. If one request exceeds the limit, any others running will also have to wait for the remainder of the current measurement period.

    On iOS, you can tell ASIHTTPRequest to automatically turn throttling on when using a WWAN (GPRS/Edge/3G) connection, and it will automatically turn it off when switching to WiFi.

    // Will limit bandwidth to the predefined default for mobile applications when WWAN is active.
    // Wi-Fi requests are not affected
    // This method is only available on iOS
    [ASIHTTPRequest setShouldThrottleBandwidthForWWAN:YES];
     
    // Will throttle bandwidth based on a user-defined limit when when WWAN (not Wi-Fi) is active
    // This method is only available on iOS
    [ASIHTTPRequest throttleBandwidthForWWANUsingLimit:14800];
     
    // Will prevent requests from using more than the predefined limit for mobile applications.
    // Will limit ALL requests, regardless of whether Wi-Fi is in use or not - USE WITH CAUTION
    [ASIHTTPRequest setMaxBandwidthPerSecond:ASIWWANBandwidthThrottleAmount];
     
    // Log how many bytes have been received or sent per second (average from the last 5 seconds)
    NSLog(@"%qi",[ASIHTTPRequest averageBandwidthUsedPerSecond]);
     

    IMPORTANT: Read this before enabling bandwidth throttling:

    • Bandwidth throttling should be considered an experimental feature: Use at your own risk.
    • Do not set the bandwidth limit too low - it’s probably best not to set it below ASIWWANBandwidthThrottleAmount
    • The actual bandwidth used by your application will always be slightly more than the limit you have set, because the measured bandwidth does not include the bandwidth used by HTTP headers.
    • The value of ASIWWANBandwidthThrottleAmount is not official, as far as I know, no bandwidth limit has been officially published.
    • You should not turn on bandwidth throttling unless your application is likely to send or receive large amounts of data. It may be best to turn it only only while performing requests that download or upload a large amount of data, and leave it off at all other times.
    • It probably goes without saying, but I make no guarantee your app won’t be rejected for using excessive bandwidth when you turn on throttling.

    Client certificates support

    If your server requires the use of client certificates, as of v1.8 it is now possible to send them with your request.

    // Will send the certificate attached to the identity (identity is a SecIdentityRef)
    [request setClientCertificateIdentity:identity];
     
    // Add an additional certificate (where cert is a SecCertificateRef)
    [request setClientCertificates:[NSArray arrayWithObject:(id)cert]];

    There is a helper function in ClientCertificateTests.m in the iPhone / iPad sample app that can create a SecIdentityRef from PKCS12 data (this function only works on iOS).

    Working with Proxies

    ASIHTTPRequest can detect system proxy settings and automatically apply them to requests. As of v1.0.6, it also supports PAC file proxy configuration, and authenticating proxies.

    By default, ASIHTTPRequest will attempt to detect proxy settings automatically. However, should you wish, you can manually set proxy settings:

    // Configure a proxy server manually
    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setProxyHost:@"192.168.0.1"];
    [request setProxyPort:3128];
     
    // Alternatively, you can use a manually-specified Proxy Auto Config file (PAC)
    // (It's probably best if you use a local file)
    [request setPACurl:[NSURL URLWithString:@"file:///Users/ben/Desktop/test.pac"]];

    Authenticating proxies

    On Mac OS, ASIHTTPRequest can auto-detect credentials used for authenticating proxies if they are specified in System Preferences. On iOS, ASIHTTPRequest cannot auto-detect the credentials used for authenticating proxies, so you either have to set them manually, use delegation to ask your controller / the user for appropriate credentials, or let ASIAuthenticationDialog ask the user for them. Once valid proxy credentials have been obtained, they are stored in the keychain (when useKeychainPersistence is on) and are automatically reused.

    Manually specifying credentials for the proxy

    NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setProxyHost:@"192.168.0.1"];
    [request setProxyPort:3128];
     
    // Set a username and password for authenticating proxies
    [request setProxyUsername:@"bencopsey"];
    [request setProxyPassword:@"password"];
     
    // For NTLM proxies, you can also set the domain (NTLM proxies are untested!)
    [request setProxyDomain:@"la.la.land"];

    Using delegation to ask for proxy credentials

    This works in the same way as using delegates to provide credentials for regular authentication, except that your delegate must respond to proxyAuthenticationNeededForRequest: (formerly proxyAuthorizationNeededForRequest:).

    Picture of the proxy authentication dialog

    Using the built-in authentication dialog (currently iOS only)

    New in v1.0.8 is the ASIAuthenticationDialog class. This can be used to ask the user for credentials for authenticating webservers and proxies.

    If your delegate does not respond to proxyAuthenticationNeededForRequest:, by default, ASIHTTPRequest will show a dialog prompting the user to supply credentials. It appears by default for proxy servers so that all apps using ASIHTTPRequest can work with authenticating proxies without any additional effort on the part of the developer.

    The proxy authentication dialog will not appear for synchronous requests.

    If you prefer not to use the proxy authentication dialog, either implement proxyAuthenticationNeededForRequest: in your proxy, or set shouldPresentProxyAuthenticationDialog to false (in which case your application will not be able to connect to authenticating proxies). If you want to change the look and feel, subclass ASIHTTPRequest, and override showProxyAuthenticationDialog to show your custom dialog or ASIAuthenticationDialog subclass.

    Miscellaneous features

    Customising the user agent

    To set the user agent your app will use, do this:

    [ASIHTTPRequest setDefaultUserAgentString:@"MyApp 1.0"]

    If you do not set a user agent, ASIHTTPRequest will create one for you. An example (for a Mac OS application):

    My Application 1.0 (Macintosh; Mac OS X 10.5.7; en_GB)

    You can also set the user agent on a per-request basis:

    [request setUserAgent:@"MyApp 1.0"]

    Continuing a request when your app enters the background on iOS

    // iOS 4+ only
    [request setShouldContinueWhenAppEntersBackground:YES];

    Monitoring network activity

    // Log the average bandwidth used (in bytes) per second over the last 5 seconds
    NSLog(@"%llu",[ASIHTTPRequest averageBandwidthUsedPerSecond]);
     
    if ([ASIHTTPRequest isNetworkInUse]) {
    	// ASIHTTPRequest has requests in progress that are using the network
    }

    Disabling automatic updates to the network activity indicator (iOS only)

    By default, ASIHTTPRequests will show the network activity indicator (in the status bar) on iOS devices when requests are using the network. If you prefer to manage this yourself, you can disable these updates:

    [ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:NO];

    Automatically retry requests when they time out

    Make requests retry a maximum of 2 times if they encounter a timeout:

    [request setNumberOfTimesToRetryOnTimeout:2];

    Configuring persistent connections

    By default, ASIHTTPRequest will attempt to keep connections to a server open so that they can be reused by other requests to the same server (this generally results in significant speed boost, especially if you have many small requests). Persistent connections will be used automatically when connecting to an HTTP 1.1 server, or when the server sends a keep-alive header. Persistent connections are not used if the server explicitly sends a ‘Connection: close’ header. Additionally, ASIHTTPRequest will not use persistent connections for requests that include a body (eg POST/PUT) by default (as of v1.8.1). You can force the use of persistent connections for these request by manually setting the request method, then turning persistent connections back on:

    [request setRequestMethod:@"PUT"];
    [request setShouldAttemptPersistentConnection:YES];

    Many servers do not provide any information in response headers on how long to keep a connection open, and may close the connection at any time after a request is finished. If the server does not send any information about how long the connection should be used, ASIHTTPRequest will keep connections to a server open for 60 seconds after any request has finished using them. Depending on your server configuration, this may be too long, or too short.

    If this timeout is too long, the server may close the connection before the next request gets a chance to use it. When ASIHTTPRequest encounters an error that appears to be a closed connection, it will retry the request on a new connection.

    If this timeout is too short, and the server may be happy to keep the connection open for longer, but ASIHTTPRequest will needlessly open a new connection, which will incur a performance penalty.

    // Set the amount of time to hang on to a persistent connection before it should expire to 2 minutes
    [request setPersistentConnectionTimeoutSeconds:120];
     
    // Disable persistent connections entirely
    [request setShouldAttemptPersistentConnection:NO];

    Forcing the use of HTTP 1.0

    [request setUseHTTPVersionOne:YES];

    Disabling secure certificate validation

    You may wish to use this for testing purposes if you have a self-signed secure certificate. I recommend purchasing a certificate from a trusted certificate authority and leaving certificate validation turned on for production applications.

    [request setValidatesSecureCertificate:NO];
     
     
  • 相关阅读:
    Python异步任务模块之-celery
    Atom 编辑器侧边栏忽略隐藏文件
    判断字符串是否为回文 python
    python 命令行工具 fire
    Appium自动化测试-iOS
    视频转换工具ffmpeg
    nodejs顺序执行shell
    Jenkins 邮箱配置及问题解决
    mac配置php
    appium镜像设置
  • 原文地址:https://www.cnblogs.com/lisa090818/p/3165305.html
Copyright © 2011-2022 走看看