What I’m trying to do:
Use zipfile to zip files uploaded by a user.
What I’ve tried and what’s not working:
It works with the regular python3 enviroment, but breaks in python 3.10 beta minimal. All the libraries import fine. Is there something I’m missing? Code Sample:
import anvil.server
import anvil.media
from anvil.tables import app_tables
import shutil
import tempfile
@anvil.server.callable
def make_zip_remote(file,zip_file_name):
with tempfile.TemporaryDirectory() as temp_dir:
#
# Need to Create File with open to control file name
#
with open(f'/tmp/{file.name}','w+') as temp_file: #TODO: BECARE BEFORE SELLING TO OTHER COMPANY. if I DONT USE tempfile, temporary files with file names that arent unique could be shared throughtout my account
#
# Need to make pdf a media blob
#
print(file.name)
anvil.media.write_to_file(file,f'{temp_file.name}')
shutil.copy(f'{temp_file.name}',f'{temp_dir}')
my_zip = shutil.make_archive(zip_file_name, 'zip', f'{temp_dir}')
tmp_file = anvil.media.from_file(f'{my_zip}', 'text/plain')
app_tables.files.add_row(file=tmp_file)
error
_1_ Messenger.png
`OSError: [Errno 30] Read-only file system: 'Test.zip'`
* `at /usr/local/lib/python3.10/zipfile.py:1251`
* `called from /usr/local/lib/python3.10/shutil.py:983`
* `called from /usr/local/lib/python3.10/shutil.py:1124`
* `called from Zip, line 33`
* `called from Form1, line 14`
I tried doing the following, but I definitely and implementing wrong.
import anvil.server
import anvil.media
from anvil.tables import app_tables
import shutil
import tempfile
import io
@anvil.server.callable
def make_zip_remote(file,zip_file_name):
with tempfile.TemporaryDirectory() as temp_dir:
#
# Need to Create File with open to control file name
#
with open(f'/tmp/{file.name}','w+') as temp_file: #TODO: BECARE BEFORE SELLING TO OTHER COMPANY. if I DONT USE tempfile, temporary files with file names that arent unique could be shared throughtout my account
#
# Need to make pdf a media blob
#
print(file.name)
buffer = io.BytesIO(file.get_bytes())
buffer.seek(0)
anvil.media.write_to_file(buffer,f'{temp_file.name}')
shutil.copy(f'{temp_file.name}',f'{temp_dir}')
my_zip = shutil.make_archive(zip_file_name, 'zip', f'{temp_dir}')
tmp_file = anvil.media.from_file(f'{my_zip}', 'text/plain')
app_tables.files.add_row(file=tmp_file)
@anvil.server.callable
def make_zip_remote(file, zip_file_name):
if not zip_file_name.endswith(".zip"):
zip_file_name += ".zip"
with tempfile.TemporaryDirectory() as temp_dir:
with anvil.media.TempFile(file) as f_name:
shutil.copy(f_name, temp_dir + "/" + file.name)
with anvil.media.TempFile() as z_name:
my_zip = shutil.make_archive(z_name, 'zip', root_dir=temp_dir)
tmp_file = anvil.media.from_file(my_zip, 'application/zip', zip_file_name)
app_tables.files.add_row(file=tmp_file)
That’s basically what I was doing - minus the brevity & simplicity - whilst also being unencumbered with the onerous weight of successfully achieving the goal
Ah I just looked at the code you edited away, and yeah I moved on to zlib after using zipfile for many years for 2 reasons:
zipfile has horrible support for file streams and the library wants a place to write to disk all the time even if it isn’t using it for anything.
zlib is also available in javascript so we can move the compression/decompression to the client browser/cpu if the use case involves ton’s of users all hogging your anvil server module resources by zipping files that have to be transferred to or from the server module uncompressed, then worked on.
I avoid javascript like the plague and even I was able to use it with anvil by just following almost any of the docs for how to use javascript with anvil:
Sorry for my late response. My solution you can’t move to client side anyway.
import zipfile#creation of zip files
zip_filename = "files.zip"
# Create a BytesIO object to hold the zip archive
zip_buffer = BytesIO()
# Create the zip archive in memory
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_archive:
# Your existing code to add the files to zip
# y all files
for file_ready in y:
# In case of reading from a database: Convert LazyMedia to BytesIO
file_ready = BytesIO()
file_ready.write(media_object.get_bytes())
file_ready.seek(0)
# Add the file_ready to the zip archive with the filename
zip_archive.writestr(filename_in_zip, file_ready.getvalue())
zip_archive.close()
zip_buffer.seek(0, 0)
# Upload file to Anvil server
file =anvil.BlobMedia("application/zip", content=zip_buffer.read(), name=now.strftime(f"%Y%m%d-%H-%M-%S-zip-files.zip")