0

As it is now the following code cannot return a tuple, with 2 elements, 1st one being a astring and then a response method.

@app.route( '/file', methods=['POST'] )
def file():

    pdata = ''
    pdata = pdata + '''<img src="/static/img/arrow.gif" align="left">'''
    return pdata, send_from_directory( filepath, filename, as_attachment=True )

What is the easiest way to have pdata print some lines before i return afile to the user?

I do NOT wish to create an extra html template just to print some lines.

3 Answers3

1

Use yield.

@app.route( '/file', methods=['POST'] )
def file():

    pdata = ''
    pdata = pdata + '''<img src="/static/img/arrow.gif" align="left">'''
    yield pdata
    for f in send_from_directory( filepath, filename, as_attachment=True ):
        yield f

FULL EXAMPLE OF IT WORKING:

from bottle import app, get, post, template, route, run

@get('/file')
@post('/file')
def file():

    pdata = '<h3>Hello<h3>'
    pdata = pdata + '''<img src="/static/img/arrow.gif" align="left">'''
    yield pdata
    yield '<br><br>HELLO WORLD'

run(host='localhost', port=8080, debug=True)
eatmeimadanish
  • 3,809
  • 1
  • 14
  • 20
  • I just tried `# Prepare selected file for download... filepath = '/home/nikos/wsgi/static/files/' yield pdata yield send_from_directory( filepath, filename, as_attachment=True ) return 'ok' ` but i'am receiving the error `TypeError: 'generator' object is not callable The view function did not return a valid response. The return type must be a string, tuple, Response instance, or WSGI callable, but it was a generator.` – Νικόλαος Βέργος Oct 09 '18 at 17:38
  • Your function is returning an iterator, use a for loop against the function and yield each result. – eatmeimadanish Oct 09 '18 at 17:40
  • Honestly though, you should read some documentation, many of your questions are answered in the documentation. – eatmeimadanish Oct 09 '18 at 17:41
  • i don't understand how you mean it. Use for where? if i'am to `yield` the pdata and send_from_directory what must the return statemnt be? – Νικόλαος Βέργος Oct 09 '18 at 17:42
  • Could you please explain to me as simple as you can your suggestion? Here is the functionality i need to do: `filename = request.form.get('filename') filepath = '/home/nikos/wsgi/static/files/' yield send_from_directory( filepath, filename, as_attachment=True ) return pdata` – Νικόλαος Βέργος Oct 09 '18 at 17:52
  • When i'm trying to run it i get `TypeError: 'generator' object is not callable The view function did not return a valid response. The return type must be a string, tuple, Response instance, or WSGI callable, but it was a generator.` When i use yield i don't have to use return? – Νικόλαος Βέργος Oct 09 '18 at 19:01
  • How am I supposed to know what your function send_from_directory is returning. This is what is causing the issue. – eatmeimadanish Oct 09 '18 at 20:16
  • If i replace `yield send_from_directory` with `return send_from_directory` it returns the file it works without error. Even if i just use `yield pdata` the same error appears, so its yield that is causing the issue. – Νικόλαος Βέργος Oct 10 '18 at 07:36
  • I removed `send_from_directory` entirely and i just left `yield pdata` and i receive the exact error message. `pdata` only holds some html lines, nothing else. – Νικόλαος Βέργος Oct 10 '18 at 07:51
  • I don't know what to tell you. You have not provided sufficient code for me to test. I posted an updated example of how it works, and confirmed it does. If you need more assistance you need to provide a complete example. – eatmeimadanish Oct 10 '18 at 17:55
  • I forgot to mention that i'am using Flask, not Bottle and every time i try to `yield pdata` i get the error `TypeError: 'generator' object is not callable The view function did not return a valid response.` – Νικόλαος Βέργος Oct 10 '18 at 19:05
  • Your initial post is literally tagged with python and BOTTLE. – eatmeimadanish Oct 11 '18 at 20:26
  • i don't know why but to me `yield` is not working at all. i cant even print a "Hello" with it. – Νικόλαος Βέργος Oct 12 '18 at 13:26
0

If your print can't output something, it may hooked by your framework.

You may try to print things in the following ways:

  • use std.err
import sys
print(pdata, file=sys.stderr)
  • logging module
import logging
logging.error(pdata)
whiledoing
  • 51
  • 6
  • What you mean by "hooked" by Bottle? Are you sure that from within a view function we can actually print a string before the return statement? I tried both way but nothing gets printed on browser or in the error_log. – Νικόλαος Βέργος Sep 23 '18 at 15:36
  • Why the following statement of returning a tuple won't work? `return pdata, static_file( filename, root='/home/nikos/public_html/static/files' )` ? – Νικόλαος Βέργος Sep 23 '18 at 15:42
  • @ΝικόλαοςΒέργος I am not family with the framework you used, but what I mean is that if the print can not work, it may caused by your framework redirect ing the stdout. You can read the documentation of your framework for more details. – whiledoing Oct 01 '18 at 08:42
  • @ΝικόλαοςΒέργος If you just want to print something in your browers. You have to write the html or js to the brower. One easy method is just put the debug information into html like `returned_html_str = '' % pdata` – whiledoing Oct 01 '18 at 08:45
  • Perhaps cna you help me with this question? https://stackoverflow.com/questions/52576913/ensure-that-values-are-passed-with-unicode-encoding – Νικόλαος Βέργος Oct 01 '18 at 12:29
  • @ΝικόλαοςΒέργος Try to use unicode to render your html template. Something like `template('.... {{filename}}', filename = filename.decode(your_locale_file_encoding))` in which `your_local_file_encoding` should be your locally file encoding. (In most case your should set it to be utf-8) – whiledoing Oct 02 '18 at 13:14
  • if you mean like this: `return template( 'files.html', authuser=auth.username, filename=filename.decode('utf-8') )` it errors out: `AttributeError: 'str' object has no attribute 'decode'` – Νικόλαος Βέργος Oct 02 '18 at 13:32
  • @ΝικόλαοςΒέργος Sorry, you are using py3. In py3, string is unicode by default, you don't need to convert the encoding. My suggestion is you may change the name of your file as just English letters, try to avoid the buggy encoding problem. – whiledoing Oct 05 '18 at 14:57
  • Since i'm using Python3 and its supposed to be unicode encoding why it has trouble downloading the file? – Νικόλαος Βέργος Oct 07 '18 at 09:12
  • Please help me with this issue where i'm describing the probelm exactly. https://stackoverflow.com/questions/52576913/generate-a-link-with-utf-8-values-and-passing-it-to-a-flask-route – Νικόλαος Βέργος Oct 07 '18 at 09:13
0
filename = request.form.get('filename')         # value comes from posted html form

# Prepare selected file for download...
if request.args:
    filename = request.args.get('filename')         # value comes from template link
    filepath = '/home/nikos/wsgi/static/files/'

    return send_from_directory( filepath, filename, as_attachment=True )

return render_template( 'files.html', authuser=auth.username, filename=filename )

I tried it as as above by sending the use to 'files.html' template so he can see the html data output and then from there i used:

<meta http-equiv="REFRESH" content="5; URL=http://superhost.gr/files/download?filename={{ filename }}">

so it can return in the same callback function to get the file. This is what i can think of.

If someone has a more clear solution please let me know.