Archive for the 'NSInvocationOperation' Category

2016/09/13 並列ダウンロードのじっけん

複数のURLをリストで渡すと、Webからダウンロードを実行するAppleScriptです。

downloaded.jpg

実行すると、デスクトップにファイルを作成します。強制的に最前面(foreground)で実行する必要はありません。

本当に並列処理できているのか確証が持てなかったので、わりと大きなデータ(書籍のサンプルPDF)を指定してみました。たぶん、並列ダウンロードしていると思うんですが、、、、

オリジナルのObjective-Cのプログラムでは、毎回同じファイル名で保存するようになっていたので、URLからファイル名を求め(lastPathComponent())、その名前で保存するようにしてみました。

NSURLのlastPathComponent()は本当に便利です。DropboxのURLとかのパラメータつきURLから普通にPure AppleScriptでファイル名を抽出するのは面倒くさい処理ですが、Cocoaの機能を利用すると楽勝です。

ダウンロードしたデータ(NSData)を直接変数に代入できるので、「いったんファイルに書き込む処理をしたくない」ような場合に本ルーチンを書き換えてファイル保存しないようにすることで、目的を達成できます。

AppleScript名:並列ダウンロードのじっけん
– Created 2016-09-13 by Takaaki Naganoya
– 2016 Piyomaru Software

– オリジナル: HTTP からファイルをダウンロードして、ローカルに保存する方法(shintarou_horiのブログ)
–http://shintarou-hori.hatenablog.com/entry/2014/03/15/193604

use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set urlList to {“http://piyocast.com/as/wp-content/uploads/2016/08/book1_20_sampler.pdf”, “http://piyocast.com/as/wp-content/uploads/2016/08/book2_20_sampler.pdf”}

set fileCount to 1

repeat with i in urlList
  set j to contents of i
  
set aURL to (current application’s |NSURL|’s URLWithString:j)
  
set aQueue to current application’s NSOperationQueue’s new()
  
set aOperation to (current application’s NSInvocationOperation’s alloc()’s initWithTarget:me selector:“execDL:” object:aURL)
  (
aQueue’s addOperation:aOperation)
end repeat

on execDL:theURL
  set imageData to current application’s NSData’s alloc()’s initWithContentsOfURL:theURL
  
set aFileName to theURL’s |lastPathComponent|()
  
my performSelectorOnMainThread:“saveData:” withObject:{imageData, aFileName} waitUntilDone:false
end execDL:

on saveData:theDataArray
  copy theDataArray to {theData, saveFileName}
  
set documentsDirectory to current application’s NSString’s stringWithString:(POSIX path of (path to desktop folder))
  
set dataPath to documentsDirectory’s stringByAppendingPathComponent:saveFileName
  
set fileManager to current application’s NSFileManager’s defaultManager()
  
  
set success to (fileManager’s fileExistsAtPath:dataPath) as boolean
  
if success then
    set retData to current application’s NSData’s dataWithContentsOfFile:dataPath
  else
    theData’s writeToFile:dataPath atomically:true
  end if
end saveData:

★Click Here to Open This Script