0

So I created a small flask program which would take a file , do some processing and returns a stream of data using yield.

I am using html form for file upload and submit. The form sends file to a python script and returns the output. The issue is that the output is presented onto a different page because of the form action attribute whereas I need the output on the same page. Probably inside a div tag.

index.html

<script>
if (!!window.EventSource) {
  var source = new EventSource('/upload');
  source.onmessage = function(e) {
    console.log(e)
    var byte = e.data;
    var res = byte.split(/\s/);
    console.log(res[0])
    $("#morse").text(res[0].slice(1,));

  }
}
</script>
<form action="/upload" method=post enctype=multipart/form-data >
    <p><input type="file" name="file" >
    <input type="submit" value="Upload" id="search_form_input">
    </form>


<div id="morse" class="info">nothing received yet</div>  // this is where is need my data

Python code

@app.route('/')
def index():
    return render_template('index.html')

@app.route("/upload", methods=['GET', 'POST'])
def streambyte():
    if request.method == 'POST':
        f = request.files['file']
        list_of_items = unAssign(f)  # some file processing
        def events():
            for i in list_of_items:
                yield "data: %s\n\n" % (i)
            time.sleep(1)  # an artificial delay

        return Response(events(), content_type='text/event-stream')

This streams the data on http://localhost:5000/upload whereas I need it on http://localhost:5000.

I tried using redirect with Response but it failed saying TypeError: 'generator' object is not callable

Duck_dragon
  • 440
  • 5
  • 17
  • You should use **Ajax** to do this kind of work. It will send an asynchronous request to the server, the server will return an answer, and after with **Javascript/Jquery** you will modify the DOM to display these new infos. [Check out this link for more info on how to use Ajax with Flask](https://stackoverflow.com/questions/52870184/get-data-from-html-and-do-some-operation-on-it-and-pass-the-data-back-to-the-f/52883461#52883461) – Tobin Nov 14 '18 at 13:46
  • Try to use Ajax or another alternative would be to render the same template with the response object. So, you would initially do render_template('some_html') and then as you process render_template('some_html', data=data) and parse the data. – Jessi Nov 15 '18 at 01:14
  • @Jessi I get that . I used ajax to send file to python. But the think is the file doesn't exist out of that post request. and I don't want to store it. So everything need to be inside that request. What I am thinking to store that data temporarily inside a pickle and delete it – Duck_dragon Nov 15 '18 at 05:21

1 Answers1

2

You may not need JavaScript to do this...

Since you need the result on the 'index.html' page (i.e http://localhost:5000), you need to create two routes for the same index page.

The first route will load the fresh form (method attribute not set), while the second will reload the process form (method attribute is set to POST). Both routes will point to same index page.

Here below is how your code should look like:-

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Flask App - Output data on same page after form submit</title>
</head>
<body>

    <form method=post enctype=multipart/form-data >
    <p><input type="file" name="file" >
    <input type="submit" value="Upload" id="search_form_input">
    </form>


    <div id="morse" class="info">nothing received yet</div>
    <h3>{{ result }}</h3>
    <h3>{{ file_path }}</h3>


<!-- this is where is need my data -->

</body>
</html>

Python code

from flask import Flask, render_template, request

app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html')


@app.route("/", methods=['GET', 'POST'])
def streambyte():
    # your file processing code is here...
    f = request.files['file']
    your_script_result = 'This variable holds the final data output'
    # your file processing code is here...

    return render_template('index.html', file_path = f, result = your_script_result)


if __name__ == '__main__':
    app.run(debug=True)

Read more from this link: Send data from a textbox into Flask?

userPyGeo
  • 3,631
  • 4
  • 14
  • 24