天天看點

[翻譯] 使用開源庫 JGDownloadAcceleration 控制下載下傳隊列,斷點下載下傳,加速下載下傳JGDownloadAcceleration

[翻譯] 使用開源庫 JGDownloadAcceleration 控制下載下傳隊列,斷點下載下傳,加速下載下傳JGDownloadAcceleration

本人對原文進行了翻譯,湊合看看,使用心得以後補上

<a href="https://github.com/jonasgessner/jgdownloadacceleration" target="_blank">https://github.com/jonasgessner/jgdownloadacceleration</a>

© 2013 jonas gessner

jgdownloadacceleration is a networking library for ios targeted at downloading large files on to the device's hard disk.

jgdownloadacceleration's main part is a concurrent nsoperation subclass (jgdownloadoperation) which handles the multipart download.

for managing and queuing multiple operations, jgdownloadacceleration provides a nsoperationqueue subclass (jgoperationqueue) which handles the networking thread, activity indicator and application background task.

jgdownloadacceleration 是一個網絡庫,用于ios開發,用來同時下載下傳多個大型檔案到裝置磁盤上的。

jgdownloadacceleration 的核心是一個并發的 nsoperation 的子類(jgdownloadoperation),專門用來處理多個下載下傳任務的。

為了管理以及隊列操作,jgdownloadacceleration 提供了一個 nsoperationqueue 的子類(jgoperationqueue),專門用來處理網絡線程,活動訓示器,以及程式背景任務。

q. how does the download acceleration even work?

問.如何加速下載下傳任務?

a. download accelerators (multipart download) use multiple network connections to download a file from a server in chunks (each connection downloads one part of the entire content). this allows to bypass bandwidth limitations set by the server and download speeds can be drastically increased.

答.下載下傳加速呢,實際上是多個網絡連結請求去下載下傳一個檔案,從一個伺服器上分段下載下傳一個檔案。這個是需要這個伺服器支援的,如果伺服器支援這種模式,就能下載下傳加速。

current version: 1.2.1

download jgdownloadacceleration

add the whole "jgdownloadacceleration classes" folder to your project

have a read through the overview section

<code>#import "jgdownloadacceleration.h"</code>

start using jgdownloadacceleration!

     1. 下載下傳jgdownloadacceleration

     2. 将整個檔案夾 jgdownloadacceleration classes 拖入你的工程當中

     3. 看一下概述區域

     4. 引入頭檔案 jgdownloadacceleration.h

     5. 開始使用jgdownloadacceleration

jgdownloadacceleration consists of 2 different classes that are available to use for networking.

jgdownloadacceleration  包含了2個不同的類,用來處理網絡下載下傳任務。

a nsoperation subclass which does the download acceleration magic.

nsoperation 的子類完成了這些功能。

<code>jgdownloadoperation</code> is restricted to http get requests and to writing downloaded content directly to the hard disk.

<code>jgdownloadoperation</code> 是被限制使用 http get 請求的,它直接将檔案寫入到了磁盤上。

parameters to pass: a <code>jgdownloadoperation</code> instance required to have the <code>url</code> parameter, and the <code>destinationpath</code> parameter set. if not the application will terminate with an assertion failure.

傳遞的參數:<code>jgdownloadoperation</code> 對象需要提供一個 url 連結,以及存儲的目的位址,如果沒有這個參數,程式将會終止并抛出 assertion 異常。

all <code>jgdownloadoperation</code> instances should be initialized with the <code>initwithurl:destinationpath:allowresume:</code>or <code>initwithrequest:destinationpath:allowresume:</code> methods, where the url or nsurlrequest, the local destination path and a <code>bool</code> to indicate whether the operation should resume (if possible) where it left of is passed. any files located at the destination path will be removed when starting the download.

所有的 <code>jgdownloadoperation</code> 執行個體對象都應該用方法 initwithurl:destinationpath:allowresume:或者 initwithrequest:destinationpath:allowresume: 來初始化。傳遞 url 位址或者 url請求,一個本地存儲的位址以及一個bool值來标示,這個下載下傳是否可以暫停操作(如果可能的話),任何被指定的檔案,在重新開始下載下傳時都會被删除掉而重新建立。

optionally, the number of connections to use to download the resource, a tag, and the retry count can be set.

當然,有幾個連結來下載下傳資源,标示符,重試的次數都可以設定。

by default the tag is 0 and the number of connections is 6. the retry count it the number of connections divided by 2.

預設情況下,标示符是0,而連結資源數是6,重試次數是2。

the readonly properties are:

隻讀屬性如下:

<code>originalrequest</code> and <code>destinationpath</code> are set in the <code>initwithurl:destinationpath:allowresume:</code> or <code>initwithrequest:destinationpath:allowresume:</code> methods and should not be changed once the operation has been initialized, therefore they are a <code>readonly</code> property. <code>contentlength</code> is the expected length (bytes) of the resource to download. this value will be 0 before the <code>requeststartedblock</code> is called. <code>error</code> returns the failure error (it will be <code>nil</code> if no error occurred). the error will also be passed in the failure block. (see below for more info on the started and the failure blocks).

<code>originalrequest</code> 以及 <code>destinationpath 在請求開始後就不能再改變了,</code> <code>contentlength</code> 是檔案大小的屬性,表示要下載下傳的檔案有多大。在<code>requeststartedblock</code> 調用之前,其值為0,出現錯誤時,傳回error(如果沒有錯誤,則傳回nil)。當然呢,這個error也會傳遞到failure的block中去。

<code>jgdownloadoperation</code> can only be initialized using either of the two custom init methods.

<code>initwithurl:destinationpath:allowresume:</code>: in this init method the request made will be a simple http get request from the given url. no more customization is possible.

<code>initwithrequest:destinationpath:allowresume:</code>: this init method allows you to use a custom nsurlrequest with <code>jgdownloadoperation</code>. the http method can only be get (default). <code>jgdownloadoperation</code> also supports the <code>range</code> header.

<code>jgdownloadoperation</code> 隻能用下面的兩種方法來初始化。

initwithurl:destinationpath:allowresume: 這個初始化方法中的request必須是http get請求,不能再設定其他的了。

initwithrequest:destinationpath:allowresume: 這個初始化方法允許你用jgdownloadoperation來定制一下請求,但是呢,這個request也隻能是get請求,<code>jgdownloadoperation</code> 支援range頭。

<code>jgdownloadoperation</code> uses blocks to communicate with a delegate.

<code>jgdownloadoperation 使用block來與代理互動。</code> 

used to be notified when the operation starts. the block passes the tag (default 0) of the operation and the expected content size of the resource. the blocks is called from the network thread.

用來訓示操作開始了。這個block将傳遞出标示值以及下載下傳資源的大小資料。這個block是被網絡線程調用的。

used to be notified when the operation finishes and to be informed about the completion state (failed with an error or not?). the completion block passes a reference to the operation, the failure block passes a reference to the operation and the error. both blocks are called from a background thread (not the network thread).

用來訓示,但這個下載下傳完成後,提示你完成的狀态值(成功或者失敗了?)。這個完成的block傳遞了一個operation,失敗的block傳遞了一個error。這兩個block都是在背景線程執行的(注意,不是網絡線程)。

used to determine, calculate, and observe various details of the current download. this block is called on the (secondary) networking thread! it is called every time a connection inside the operation receives a chunk of data (which is automatically written to the disk). the current progress, current download speed, average download speed (and using that an estimation for the remaining time) can be calculated. for average and current speed a variable in needed to store the time intervals from the last call of the block (for the current speed) and from when the operation started. see the example project for an implementation of this

用來确定、計算、以及觀察目前下載下傳任務的詳細細節。這個block是在另外一個網絡線程被調用的。當一個操作中的網絡連接配接接受了一些資料時将會自動調用。目前的下載下傳進度,目前的下載下傳速度,平均的下載下傳速度都被計算出了。對于平均的以及目前的速度計算,需要一個變量來儲存每次調用時的時間戳,請看工程樣例。

<code>nsuinteger bytesread</code> indicates the size of the bytes read (not since the last call of the block, its pretty complicated because this block is called for each connection, passing the number of bytes the specific connection loaded since this specific connection last loaded a chunk of bytes).

<code>unsigned long long totalbytesreadthissession</code> the total number of bytes read in this current session. (e.g if a download is paused at 50% and then resumed, this parameter will start from 0)

<code>unsigned long long totalbyteswritten</code> the total bytes read in total.

<code>unsigned long long totalbytesexpectedtoread</code> the expected content size of the resource.

<code>nsuinteger tag</code> the tag of the operation, very handy for managing multiple operations in a queue. 

internally this class uses a bunch of helper classes. these should not be touched by anything but the <code>jgdownloadoperation</code>. 

<code>jgdownloadoperation</code> uses a metadata file to store the progress of each connection, to allow the operation to resume when failed or cancelled. the metadata file is stored at the destination path with the file extension <code>jgd</code>. the metadata file will automatically be removed when the operation finishes with success. passing <code>yes</code> for "allowresume" in the custom <code>init</code> methods will result in a attempt to read the metadata file and resume from the last known state. if the metadata file or the partial downloaded content is not available then the download will start from the beginning. if <code>no</code> is passed for "allowresume" then no metadata files will be written and the download will always start from the beginning. if reading the metadata file is not possible (if the file does not exist) the download will start from the beginning, overwriting any existing progress. 

<code>jgdownloadoperation</code> 使用中繼資料來存儲每個連結的下載下傳進度,允許一個下載下傳連結斷掉後能夠斷點續傳或者取消掉這個下載下傳連結。這個中繼資料存儲在指定的檔案路徑中,字尾為jgd。當下載下傳成功後,這個中繼資料會自動移除。給allowresume傳遞yes參數,将會試圖讀取這個中繼資料檔案,來恢複最後一個儲存的下載下傳狀态。如果,這個中繼資料或者下載下傳的檔案沒有了,那麼下載下傳将會從頭開始。如果給allowresume傳遞了no參數。那麼,将不會産生中繼資料檔案,而且,每次都會從頭開始下載下傳。如果,無法讀取中繼資料檔案(或者這個檔案不存在),那麼,下載下傳将會從頭開始,重寫存在的進度。

<code>cancel</code> will stop the download, synchronize the metadata file to allow resuming the download later and leave the partially downloaded file on the disk. the failure completion block will be called with an <code>nsurlerrorcancelled</code> error.

<code>cancelandclearfiles</code> will stop the download and remove the partially downloaded file as well as the metadata file from the disk. neither the success completion block or the failure completion block will be called.

cancel 将會停止下載下傳,并同步的寫中繼資料檔案,記錄目前下載下傳的資訊,并将部分下載下傳的檔案儲存在磁盤上。如果失敗了,失敗的block将會被調用。

cancelandclearfiles 将會停止這個下載下傳,并移除這個下載下傳的檔案以及中繼資料檔案,不會調用任何的block

a nsoperationqueue subclass which is targeted at enqueuing only <code>jgdownloadoperation</code> objects.

<code>jgoperationqueue</code> handles the shared network thread used by all <code>jgdownloadoperation</code> instances. once all operations are finished the queue exits the networking thread. queue optionally, <code>jgoperationqueue</code> handles the status bar networkactivityindicator, according to the number of enqueued operations and the background task used for networking requests when the app runs in the background.

note that when setting <code>handlebackgroundtask</code> to <code>yes</code>, the app's info.plist file needs to have "application uses wi-fi" set to <code>yes</code>.

nsoperationqueue 的子類,隻能用來給<code>jgdownloadoperation</code> 對象進行入隊操作。

<code>jgoperationqueue</code> 處理共享的網絡線程,被所有的執行個體對象<code>jgdownloadoperation使用着,一旦所有的操作都結束了,這個隊列就從網絡線程中退出。當然,<code>jgoperationqueue</code> 處理了狀态欄上的網絡訓示器,當app在背景運作時。</code>

注意,當把 <code>handlebackgroundtask</code> 設定成yes時,這個app的 info.plist 檔案需要将 application uses wi-fi 設定成yes。

an example usage can be found in the sample project.

in order to take advantage of multipart download, the server from which you download a content needs to support the <code>range</code> http header. if it doesn't then <code>jgdownloadacceleration</code> will simply use 1 connection to download the content conventionally.

為了體驗多點下載下傳檔案,你下載下傳檔案的伺服器需要支援range http頭,否則,<code>jgdownloadacceleration</code> 隻會用一個連結來下載下傳這個檔案。

<code>jgdownloadacceleration</code> is built for use with arc and weak references. this means that ios 5 or higher is required for using <code>jgdownloadacceleration</code>

if your project doesn't use arc: you must add the <code>-fobjc-arc</code> compiler flag to all jgdownloadacceleration files in target settings &gt; build phases &gt; compile sources.

這是arc的,用于非arc項目,請添加标示 <code>-fobjc-arc</code>

使用教程:

@interface rootviewcontroller ()

{

    jgoperationqueue *q;

}

@end

------------------------------------------------------------------------------------------

ns_inline nsurlrequest *neturlrequest(nsstring *netpath)

    //建立簡單的網絡請求

    return [nsurlrequest requestwithurl:[nsurl urlwithstring:netpath]];

ns_inline nsstring * createfileorfolderpathforsandbox(nsstring *filepath)

    /*

     /documents

     /library/caches

     /library/preferences

     /tmp

     */

    return [nshomedirectory() stringbyappendingstring:filepath];

// 開始組織一個下載下傳

    jgdownloadoperation *operation =

    [[jgdownloadoperation alloc]

     initwithrequest:neturlrequest(@"http://wallpapers.wallbase.cc/manga-anime/wallpaper-1160697.jpg")

     destinationpath:createfileorfolderpathforsandbox(@"/documents/wallpaper-1160697.jpg")

     allowresume:yes];

    // 使用tag值來标示每一個不同的下載下傳

    /* -----

    operation.tag = .....

    ----- */

    // 計算時間相關

    __block cftimeinterval started;

    // 下載下傳成功後執行的block

    [operation setcompletionblockwithsuccess:^(jgdownloadoperation *operation)

    {

        double kblength = (double)operation.contentlength/1024.0f;

        cftimeinterval delta = cfabsolutetimegetcurrent() - started;

        nslog(@"success! downloading %.2f mb took %.1f seconds, average speed: %.2f kb/s",

              kblength/1024.0f, delta, kblength/delta);

    }

    failure:^(jgdownloadoperation *operation, nserror *error)

        nslog(@"operation failed: %@", error.localizeddescription);

    }];

    // 下載下傳進度的block

    [operation setdownloadprogressblock:^(nsuinteger bytesread, unsigned long long totalbytesreadthissession, unsigned long long totalbyteswritten, unsigned long long totalbytesexpectedtoread, nsuinteger tag) {

        cftimeinterval delta = cfabsolutetimegetcurrent()-started;

        nslog(@"progress: %.2f%% average speed: %.2f kb/s", ((double)totalbyteswritten/(double)totalbytesexpectedtoread)*100.0f, totalbytesreadthissession/1024.0f/delta);

    // 開始下載下傳的block

    [operation setoperationstartedblock:^(nsuinteger tag, unsigned long long totalbytesexpectedtoread) {

        started = cfabsolutetimegetcurrent();

        nslog(@"operation started, jgdownloadacceleration version %@", kjgdownloadaccelerationversion);

    // 設定6個連結同時下載下傳一個檔案

    [operation setmaximumnumberofconnections:6];

    // 設定失敗時重複3次

    [operation setretrycount:3];

    if (!q) {

        q = [[jgoperationqueue alloc] init];

        q.handlenetworkactivityindicator = yes;

        q.handlebackgroundtask = yes;

    // 開始下載下傳隊列

    [q addoperation:operation];