Home > database >  Python Flask - Make uploaded "file chosen" name stick on the HTML page
Python Flask - Make uploaded "file chosen" name stick on the HTML page

Time:02-16

I have two input buttons. One is for uploading a file, and the other one is a submit button that adds the uploaded file to the database.

My problem is, after I submit the file, the first button that's used for uploading goes back to "No file chosen" next to the button. However, I want the uploaded file name to "stick" to the UI/html page as the file chosen.

Here is my File class:

class Files(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, unique=True, nullable=False)
    data = db.Column(db.LargeBinary)

Here is my HTML code:

<td>
    <form  action="{{url_for('main.upload_file')}}" method="post" enctype="multipart/form-data">
        <input type="hidden" name="id" value="{{row.id}}">
        <input style="margin-bottom: 5px;" type="file" accept=".csv" name="csvfile" id="upload" value ="{{row.name}}"> <br>
        <input style="margin-bottom: 10px;" type="submit" name="" value="Submit"> <br>
    </form>
    <a href={{ url_for('main.files') }}>Go to Downloads Page</a>
    <br>
</td>

I've tried making the value attribute equal to the file name getting passed in ex. value ="{{row.name}}" for the file type <input> above, but that doesn't keep the file chosen name on the page after submission either. I can't find any videos or posts that deal with this problem, so I would really appreciate any guidance. TIA!

CodePudding user response:

I don't know if it is possible to default the value the file-input field shows but what you could do is just have a row above the input field showing the currently uploaded/chosen file (if there is any). So something like this:

<td>
    <form  action="{{url_for('main.upload_file')}}" method="post" enctype="multipart/form-data">
        <input type="hidden" name="id" value="{{row.id}}">
        {% if row.name %}
            <p>Currently chosen file: {{row.name}}</p>
            <p>You can select a new file below</p>
        {% endif %}
        <input style="margin-bottom: 5px;" type="file" accept=".csv" name="csvfile" id="upload"> <br>
        <input style="margin-bottom: 10px;" type="submit" name="" value="Submit"> <br>
    </form>
    <a href={{ url_for('main.files') }}>Go to Downloads Page</a>
    <br>
</td>

CodePudding user response:

I think setting a default value for an input field of type file is forbidden for security reasons.
However, if you want to keep the name of the selected file, you can aim for a transfer with AJAX. Here you can suppress the standard behavior of the form. The page is not reloaded and the form is not reset.
The example below shows you how it works.

Flask (app.py)
from flask import Flask
from flask import (
    render_template,
    request,
)

app = Flask(__name__)

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

@app.route('/upload-file', methods=['POST'])
def upload_file():
    if 'csvfile' in request.files:
        file = request.files['csvfile']
        if file.filename != '':
            # handle file here!
            return '', 200
    return '', 400
HTML (templates/index.html)
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <form name="my-form" method="post">
      <input type="file" name="csvfile" />
      <input type="submit" />
    </form>

    <script type="text/javascript">
      ((uri) => {
        const elem = document.querySelector('form[name="my-form"]');
        elem.addEventListener('submit', evt => {
          evt.preventDefault();
          const formData = new FormData(evt.target);
          fetch(uri, {
            method: 'post',
            body: formData
          }).then(resp => {
            if (resp.status === 200) {
              console.log('Submit successful.');
            }
          });
        })
      })({{ url_for('.upload_file') | tojson }});
    </script>
  </body>
</html>
  • Related