FTP Text File from server

I am creating a gateway script that will download a text file from a corporate server. The text file is small only a few KBs. I'm not a Python/Java programmer so this is a bit foreign to me.

I started with the built-in FTPlib which would allow me to transfer the file but while the script would complete almost immediately, it would be several minutes before data was in the text file.

Searching the forums ftp-client-speed-via-scripting and online pointed me in the direction of using the java.net.urlconnection method. I found several examples of this and have it downloading the file in a few seconds.

Except, the file is "binary gibberish" not human readable text. I believe this has to do with InputStream but not sure where/how I need to convert it to human readable text.

import os
from java.net import URL
from java.net import URLConnection
from java.io import BufferedReader
from java.io import InputStream
from java.io import InputStreamReader

downloadFile("dwb.dat", "C:\\FILES\\")

def downloadFile(fileName, folder):
	inputStream = getInputStream("user", "password", "127.0.0.1", "usr/dwb.dwn")

	streamReader = InputStreamReader(inputStream)
	reader = BufferedReader(streamReader)

	fileData = []
	line = reader.readLine()
	while line != None:
		fileData.append(line)
		line = reader.readLine()
	inputStream.close()
	saveFilePath = os.path.join(folder, fileName)
	try:
		file = open(saveFilePath, 'w')
		print saveFilePath
		for line in fileData:
			file.write("%s\n" % (line))
			print "%s\n" % (line)
		file.close()
		print "File Written"
	except Exception, ex:
		writeMessage("Error writing %s : %s" % (fileName, str(ex)))
	

def getInputStream(user, pwd, IP, filename):
	ftpUrl = "ftp://%s:%s@%s/%s" % (user, pwd, IP, filename)
	url = URL(ftpUrl)
	try:
		url.close()
	except:
		pass
		FTPConnection = url.openConnection()
		inputStream = FTPConnection.getInputStream()
		url.close()
		return inputStream

i guess this is just a copy paste isusue that the index is wrong?
houls be this right?

    except:
		pass
FTPConnection = url.openConnection()
inputStream = FTPConnection.getInputStream()
url.close()
return inputStream

anyways i dont think you are supposed to close it before using the stream (?)

Adapted (moderately) from ChatGPT output, this function should work, if your original snippet worked at all:

from java.io import ByteArrayOutputStream
from java.net import URL, URLConnection

def download_file(ftp_url, username, password, filename):
    url = URL("ftp://{}:{}@{}/{}".format(username, password, ftp_url, filename))
    conn = url.openConnection()
    conn.setDoInput(True)

	inputStream = conn.inputStream
	byteOutputStream = ByteArrayOutputStream()
    try:	
	    inputStream.transferTo(byteOutputStream)
    	return byteOutputStream.toByteArray()
    finally:
    	inputStream.close()
    	byteOutputStream.close()

# Usage
byte_array = download_file("ftp.example.com", "username", "password", "file.txt")
system.file.writeFile("path", byte_array)

The trick is to go "all in" on Java standard library stuff and avoid Jython's entirely, basically. That is, return a Java byte array instead of a Jython list, etc. The transferTo function is an interface default method that's "new" (as of Java 9) so lots of online resources aren't aware of it yet, but it automatically does a buffered transfer from an input stream to an output stream. I wrote the method to return a plain byte array because that gives you maximum flexibility; the builtin system.file.writeFile method can handle that byte array directly and write it out to an actual file.

1 Like

Yes. I picked up where I left of on Friday without cleaning up the code before posting.. That url.close() isn't supposed to be there.

I will work with this. I did not think to try ChatGPT for this task. Thank you.

Be very careful with ChatGPT w.r.t. Ignition. It's not even close to good enough to be blindly trusted. In the very first answer I got, it gave me Java code and imported a third party library when I explicitly asked for Jython and the Java standard library. In the second answer, when coached, it still gave me an unnecessarily complicated answer that wasn't aware of the transferTo function. If I didn't already know what I was doing, I wouldn't have been able to 'coach' it through these things or fix the final snippet.

3 Likes

I tried this out. Interestingly enough the file output is the same
"óðôù÷ökðñõðð÷kòðòôññðòkðððñ÷ùö÷KðððkÄÙ@@@@@@@"

This leads me to believe this is an 'issue' with the FTP server, not returning the data in the proper format.

I ended up using the apache.commons.net instead. This allows you to specify the file type. It worked on the first try.

1 Like