Skip to content
Advertisement

Is there a way to parse a file through to a tag in HTML

I’m trying to make a private file host and I have it set to return a send_file() when the, for example, /media/someSong.mp3 url is called.

But I want to make it more styled so when you visit /media/someSong.mp3, instead of your browser trying to play that MP3 in it, it will use a HTML page with a tag that parses the send_file() sent by an argument.

Currently, I have this:

@app.route('/media/<mediaID>')
def mediaStuff(mediaID):
    try:
        return render_template('parse-it.html', title=title, media_file=send_file(f'./media/{mediaID}'))
        # return send_file(f'./media/{mediaID}')
    except FileNotFoundError:
        return 'The media you tried to view doesn't exist.'

And here is what I have in my templates/parse-it.html file:

{% extends "base.html" %}
{% block content %}
    <h1>You are now viewing ...!</h1>
    <source src={{media_file}}>
{% endblock %}

However all I see is <Response 200 OK> or something like that. No file to be seen!

Would I use a get_file() and then return Response(getfileVar) in that media_file argument?

Advertisement

Answer

send_file returns a Response object. It makes no sense to pass this to the template.
So you need two endpoints. One to display your website containing the media element and one to stream the file from the directory. I recommend using send_from_directory for this.

This is a simple example that lists all files within a directory and offers them for playback or viewing. The distinction is made based on the mime type of the file. This is determined via guess_type.
The exmpale uses the instance path to ensure separation of files and application.

import os
from flask import (
    Flask,
    render_template,
    send_from_directory
)
from mimetypes import guess_type

app = Flask(__name__)
app.config['MEDIA_FOLDER'] = os.path.join(app.instance_path, 'media')

try:
    os.makedirs(app.config['MEDIA_FOLDER'])
except:
    pass

def listfiles(target):
    for filename in os.listdir(target):
        mimetype = guess_type(os.path.join(target, filename))
        yield (
            filename,
            mimetype,
        )

@app.route('/')
def index():
    files = listfiles(app.config['MEDIA_FOLDER'])
    return render_template('index.html', **locals())

@app.route('/media/<path:filename>')
def media(filename):
    return send_from_directory(
        app.config['MEDIA_FOLDER'],
        filename
    )
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>

    {% for filename, type in files -%}
      <div>
        {% set mimetype, encoding = type -%}
        {% if mimetype.startswith('audio') -%}
        <audio controls>
          <source src="{{ url_for('media', filename=filename) }}" type="{{ mimetype }}">
        </audio>
        {% elif mimetype.startswith('image') -%}
        <img src="{{ url_for('media', filename=filename) }}" />
        {% endif -%}
      </div>
    {% endfor -%}

  </body>
</html>
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement