0

In my project, I can save files into the directory and save its path to the database. Here is the code

def save_file(form_file):
    random_hex = secrets.token_hex(8)
    _, f_ext = os.path.splitext(form_file.filename)
    picture_fn = random_hex + f_ext
    picture_path = os.path.join(app.root_path, 'static/files', picture_fn)
    form_file.save(picture_path)
    return picture_fn

@app.route('/ticket/<int:ticket_id>',methods=['GET','POST'])
@login_required
def ticket(ticket_id):
    ticket = Tickets.query.get_or_404(ticket_id)
    com = Comment.query.filter_by(ticket_id=ticket.id).first()
    form = CommentForm()
    attachform = AttachForm()
    if form.validate_on_submit() and form.body.data:
        comment = Comment(body=form.body.data,ticket_id=ticket_id,author = current_user.username)
        db.session.add(comment)
        db.session.commit()
        flash('Your comment has been published.')
        return redirect(url_for('ticket', ticket_id=ticket_id))
    if attachform.validate_on_submit():
        if attachform.file.data:
            picture_file = save_file(attachform.file.data)
            attachment = Attachment(file=picture_file,ticket_id=ticket_id)
            db.session.add(attachment)
        db.session.commit()
        flash('Your file has been published.')
        return redirect(url_for('ticket', ticket_id=ticket_id))
    file = url_for('static', filename='files/' + str(ticket.attach))
    return render_template('ticket.html', title=ticket.title,file=file ,ticket=ticket,form=form,comment=com,attachform=attachform)

Now how do i make so that when i click on the name of the file it would get downloaded? Here is my html file

{% for fil in ticket.attach %}
        <ul class="list-group">
            <a href="{{ file }}" download class="list-group-item list-group-item-action"> {{ fil }}</a>
        </ul>
    {% endfor %}

but it downloads some weird html file not the actual file

4
  • Typo in template code for fil in ticket.attach ... {{file}}?
    – v25
    Commented Sep 6, 2020 at 23:34
  • I did change this typo but still doesn't work
    – barcaman
    Commented Sep 7, 2020 at 0:01
  • I'm guessing str(ticket.attach) in that second last line isn't returning what you think it is. I'd either add a print (str(ticket.attach)) line in there to debug, or view the source of the rendered page to ensure the correct link is being rendered in that href attribute. Either way: There's probably a good case for creating a separate route (with an auth decorator) which returns the file (using send_file), which has been stored in a separate 'uploads' directory, rather than serving it from 'static/'. Unless of course you want user uploads to be public.
    – v25
    Commented Sep 7, 2020 at 10:19
  • @v25 Thank you, I was able to manage it to work. I will attach the correct answer down below. Appreciate your help
    – barcaman
    Commented Sep 8, 2020 at 2:51

1 Answer 1

1

As @v25 suggested I've created a separate download function with send_from_directory flask extension.

 @app.route('/uploads/<path:filename>', methods=['GET', 'POST'])
    def download(filename):
        uploads = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'])
        return send_from_directory(directory=uploads,filename=filename, as_attachment=True)

html file

{% for file in ticket.attach %}
        <ul class="list-group">
            <a href="{{ url_for('download', filename=file) }}" download class="list-group-item list-group-item-action"> {{ file }}</a>
        </ul>
    {% endfor %}
1
  • Glad you got this working. Nice one on posting the follow-up also :)
    – v25
    Commented Sep 8, 2020 at 10:39

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.