justpy icon indicating copy to clipboard operation
justpy copied to clipboard

mime type and filename of dynamic download

Open eudoxos opened this issue 4 years ago • 8 comments

In this MWE, /download_zip should cause download of on-demand file with user-set Content-type and Content-disposition. As far I see, this is currently not possible with JustPy (starlette has StreamingResponse just for that), could I get some inspiration how to work around that limitation? (besides writing the file on disk and serve it as a static file)

import zipfile, io, sys
sys.path.append('/home/eudoxos/build/justpy')
import justpy as jp

@jp.SetRoute('/')
def main(): return jp.WebPage(components=[jp.A(text="Download ZIP",href="/download_zip")])

@jp.SetRoute('/download_zip')
def make_zip():
    wp=jp.WebPage()
    buf=io.BytesIO()
    z=zipfile.ZipFile(buf,mode='w',compression=zipfile.ZIP_DEFLATED)
    z.writestr('something.txt','Something.')
    z.writestr('something-else.txt','Something else.')
    wp.html=buf.getvalue()
    # returns webpage with ZIP writtes byte's repr, not data itself (see image below)
    return wp

jp.justpy()

image

eudoxos avatar Dec 02 '20 12:12 eudoxos

I need to think about this. Maybe this discussion https://github.com/tiangolo/fastapi/issues/58 can provide some inspiration meanwhile.

elimintz avatar Dec 02 '20 17:12 elimintz

As a suggestion, trivial PR #182 allows returning starlette Response object. The example below then downloads the dynamically-generated file.

It is important to create the href with target="_blank" which will open a new tab (it closes immediately when the download starts); without it, connection to the page would be interrupted (click OK to reload).

import zipfile, io, sys
import justpy as jp
import starlette.responses

@jp.SetRoute('/')
def main(): return jp.WebPage(components=[jp.A(text="Download ZIP",href="/download_zip",target="_blank")])

@jp.SetRoute('/download_zip')
def make_zip():
    wp=jp.WebPage()
    buf=io.BytesIO()
    z=zipfile.ZipFile(buf,mode='w',compression=zipfile.ZIP_DEFLATED)
    z.writestr('something.txt','Something.')
    z.writestr('something-else.txt','Something else.')
    buf.seek(0)
    return starlette.responses.StreamingResponse(
        content=buf,
        headers={'Content-Disposition':'attachment; filename="myfancyname.zip"'},
        media_type='application/zip'
    )
    return wp

jp.justpy()

eudoxos avatar Dec 03 '20 06:12 eudoxos

Nice and simple solution, thanks. I'll accept the PR and make the change for the next version. What is missing to make it a general solution, if anything?

elimintz avatar Dec 03 '20 15:12 elimintz

For bypassing JustPy, it is complete as far I see.

An cool thing would be server-initiated download without opening the extra tab via target="_blank", but I am not sure what is possible. And for my purposes, I am quite happy with this solution.

eudoxos avatar Dec 03 '20 17:12 eudoxos

Hello, The download zip folder is empty with the example. How can I return not empty zip file ? Regards

Lefort-Antoine avatar Jul 11 '22 09:07 Lefort-Antoine

Can you elaborate on the problem? Possibly share some code to understand what the problem is?

sandeep-gh avatar Jul 12 '22 16:07 sandeep-gh

I execute the same code than eudoxos commented on 3 Dec 2020 And my zipfile is empty.

Lefort-Antoine avatar Jul 12 '22 17:07 Lefort-Antoine

Will this be for version 0.0.3 or has it been done?

WolfgangFahl avatar Aug 20 '22 11:08 WolfgangFahl

You might want to migrate to nicegui if you have this problem

WolfgangFahl avatar Sep 20 '23 09:09 WolfgangFahl