Perspective download zip file with several files inside

Hello there,

I've created an application using perspective. I use it to record data into a database, and then download the recorded data. I'm able to download the data in a csv file, but I can only download one csv file / one table of the database at a time. Now what I'd like to do is to be able to download a zip file with csv files inside that corresponds to the tables of the database.
My question is: is it possible possible to do that with the command "system.perspective.download" (the one that I use to download the csv file for now) or I need to use a library ?

Thanks!

I happen to do something very similar:

import io
import zipfile
import jarray

def bytestring_to_jarray(bstring):
	"""
	Convert a Python byte string into a Java jarray

	It's saner to consistently pass byte streams as either the Java-based jarray
	or the Python-based bytearray, but don't mix and match. In particular, Ignition's
	system.file.writeFile doesn't handle the Python types properly. But, Jython's
	file.write doesn't handle the Java types properly.

	I recommend sticking with the Java jarray as much as possible when working in Ignition.

	This function provides a quick way to convert from the Python types to a Java jarray.
	It should've been possible to just do jarray.array(bytearray(), 'b') but Jython seems
	to have a bug.

	If you need to convert back, it's as simple as bytearray(javaTypeData)
	"""
	return jarray.array(((x if x < 128 else (x - 256)) for x in bytearray(bstring)),'b')

def datasets_to_zip(filenames, datasets):
	with io.BytesIO() as tmp_buff:
		with zipfile.ZipFile(tmp_buff, 'w', zipfile.ZIP_DEFLATED) as zfile:
			for file_name, dset in zip(filenames, datasets):
				zfile.writestr(file_name, system.dataset.toCSV(dset))
		tmp_buff.flush()
		byte_result = bytestring_to_jarray(tmp_buff.getvalue())
	return byte_result

In my case I was keeping the content in dataset form until the last moment, but you could pass a bunch of CSV strings around as easily as datasets and remove the toCSV function.

I hope this helps.

Oh, and you might not need to convert from the Python bytearray to the Java jarray for system.perspective.download, but it's probably safer and I definitely had to before passing the data to system.file.writeFile. When I didn't have that conversion step, the file still wrote okay and looked almost right, but it was corrupted.

2 Likes

Thanks for you answer I'll see if I can solve my problem with it!

Just wanted to say a quick thank you to justin.brzozoski, I definitely would have taken me a long time to figure out to convert from the Python bytearray to the Java jarray.

Thank you very much for sharing!

1 Like

As an exercise to myself, I wanted to see if I could do the same thing with the standard Java library. It produces a jarray as output automatically, and should be more efficient in Jython since it is java-based.

import java.util.zip.ZipOutputStream as ZipOutputStream
import java.io.ByteArrayOutputStream as ByteArrayOutputStream
import java.util.zip.ZipEntry as ZipEntry

def datasets_to_zip(filenames, datasets):
    byte_stream = ByteArrayOutputStream()
    zip_stream = ZipOutputStream(byte_stream)
    for file_name, dset in zip(filenames, datasets):
        zip_stream.putNextEntry(ZipEntry(file_name))
        zip_stream.write(system.dataset.toCSV(dset))
    zip_stream.close()
    return byte_stream.toByteArray()
4 Likes

Thanks for sharing this!

That is working very well, thank you so much!