Download small text file from a URL

I have a small text file that is located on Box with a specific URL link. The text file has a small list of data that I update regularly and I need the text file to be downloaded and to replace (update) an existing text file (with the same name) on each user’s computer.

I have an applescript app that reads that data and executes a procedure. I need that app to download the updated text file using a URL link in a format similar to “https://box.com/s/12a3bc45d6efg7hijklm8nopqrw”. The filename and the location on the user’s computer is in the Applications folder under Clients:Utilities:TextFile.txt

I’m looking for a script that I can insert into my existing script that will download and update the text file each time the script is run.

Thanks!

use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
use scripting additions

property sourceURL : "https://box.com/s/12a3bc45d6efg7hijklm8nopqrw"
property textFilePath : "/Applications/Clients/Utilities/TextFile.txt"

on updateTextFile()
	set |⌘| to current application
	set sourceURL to |⌘|'s class "NSURL"'s URLWithString:(sourceURL)
	-- Download the text from the URL
	set {theText, anyError} to |⌘|'s class "NSString"'s stringWithContentsOfURL:(sourceURL) usedEncoding:(missing value) |error|:(reference)
	if (anyError is missing value) then
		-- Ensure that the destination folder exists.
		set destinationURL to |⌘|'s class "NSURL"'s fileURLWithPath:(textFilePath)
		set destinationFolderURL to destinationURL's URLByDeletingLastPathComponent()
		tell |⌘|'s class "NSFileManager"'s defaultManager() to ¬
			createDirectoryAtURL:(destinationFolderURL) withIntermediateDirectories:(true) attributes:(missing value) |error|:(missing value)
		-- Write the text to the file, creating the file if it doesn't exist, overwriting it if it does.
		set {success, anyError} to theText's writeToURL:(destinationURL) atomically:(true) encoding:(|⌘|'s NSUTF8StringEncoding) |error|:(reference)
	else
		-- Problem downloading the text.
		set errMsg to anyError's localizedDescription() as text
		display dialog errMsg buttons {"Stop", "Continue …"} cancel button 1
	end if
end updateTextFile

updateTextFile()

-- Existing script code here.
-- You may need to make adjustments if you have the text file path set as an HFS path.

I get a the following error message

class “NSURL” doesn’t understand the “URLWithString_”

Sounds as if you’ve missed out the use framework “Foundation” line or miscopied something. :confused:

Sorry about that. I updated the script and it seems to work fine, but the text file it downloads doesn’t have the same data as the text file on Box. The data on Box is simply two columns of data; server names and IP Addresses. Here’s a small sample of what gets downloaded:

Box

etc…

Not sure what is happening?

Any thoughts?

First, you need the URL of embedded in webpage TXT file. To see, what URLs one webpage contains, you can do following:

  1. open the page in web browser. (I used “https://www.apple.com” for my test here)
  2. run this script:
set JS to "var URLs = [];
function collectIfNew(url) {
if( URLs.indexOf(url) == -1 ) {
URLs.push(url);
}
}
function processDoc(doc) {
var l = undefined;
try {
// If the document is from a different protocol+domain+port than the main page (an iframe to a foreign location), this may throw a security exception. If so, note it and move on.
l = doc.links;
} catch(e) { console.warn(e) }
if( l !== undefined ) {
for( var i = 0; i < l.length; i++ ) { collectIfNew(l[i].href) }
}
}
function processFrameset(f) {
for( var i = 0; i < f.length; i++ ) { process(f[i]) }
}
function process(o) {
if( o.frames !== undefined && o.frames.length != 0 ) {
// It is a frameset
processDoc(o.document); // Process its links. Normal framesets probably have no links, but iframe-based framesets probably have many links.
processFrameset(o.frames);
} else {
// It is a document
processDoc(o.document);
}
}
process(window);
URLs;
"

set linkURLs to {}
tell application "Safari" to set linkURLs to do JavaScript JS in front document

The script returns 99 URLs, but I want only 1 of them:
https://www.goldmansachs.com/terms-and-conditions/Apple-Card-Customer-Agreement.pdf

Knowing the URL of needed PDF, I can download it to my desktop:

set neededLink to quoted form of ("https://www.goldmansachs.com/terms-and-conditions/Apple-Card-Customer-Agreement.pdf")
set destinationFile to quoted form of (POSIX path of (path to desktop folder)) & "TEST.pdf"

do shell script "curl -o " & destinationFile & space & neededLink

OK. Do I insert the JS value into the code somewhere?

No need. You need only find the proper URL of your text file on web page, using the first script. In your main script you need only the second snippet.

As you see from my example, the PDF is not stored on the web page “www.apple.com”, but on the other resource. So, you should find proper URL - where is stored your Text file itself. Most likely, your proper URL will ended with .txt extension.

I’m sorry I don’t follow. Is there a way I can send you a test link via a private channel?

To understand, here is one other, similar workaround to download files from URL:


-- OPEN WEB PAGE
tell application "Safari" to open location "https://www.stats.govt.nz/large-datasets/csv-files-for-download/"

-- WAIT WHILE THE WEB PAGE IS LOADED
tell application "System Events" to tell application process "Safari"
	repeat until (UI element "Reload this page" of group 2 of toolbar 1 of window 1 exists)
		delay 0.1
	end repeat
end tell

-- GET CSV FILE'S LINKS ONLY
tell application "Safari" to tell the front document
	set CSVfiles to ¬
		do JavaScript "Array.from(document.links,
                                  x=>x.href)
                            .filter(x=>x.indexOf('.csv')!=-1);"
end tell

-- DOWNLOAD 2 of THEM to my DOWNLOADS FOLDER
repeat with i from 1 to 2
	set aLink to quoted form of (item i of CSVfiles)
	set destinationFile to quoted form of ((POSIX path of (path to downloads folder)) & "csvFile" & i & ".csv")
	do shell script "curl -o " & destinationFile & space & aLink
end repeat