7
\$\begingroup\$

I am developing a web application in Flask - Python.

My goal is to let the user upload an mp3/wav file. This file will (for the scope of this question) get processed by the server and a picture showing the waveform of the audio file will be shown to the user.

My concern is that I am not experienced with neither Flask nor web applications. I would like this audio file to be saved somewhere temporarily, then get deleted. Similarly, I would like the picture of the waveform to just be shown without being saved after the user sees it. This is because I expect all the mp3/wav files to be different - there is no point in saving them.

Right now I have this method that gets called when a user uploads file:

def handle_file(file):
  filename = secure_filename(file.filename)
  filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
  file.save(filepath)
  mir.save_plot(filepath)
  os.remove(filepath)
  plot_filepath = PLOT_FOLDER + 'audio.png'
  return plot_filepath

As you can see, I first save the audio file to a directory in the server, then process it (mir.save_plot does that), then I remove it, and then I return the plot_filepath which will be used in the template to show the final plot picture.

The mir.py file is the following:

import librosa
import plot as plt

def save_plot(filename):
    y, sr = librosa.load(filename)
    plt.plot(y, 'audio', 'time', 'amplitude')

The plot.py file:

import matplotlib.pylab as plt

def plot(vector, name, xlabel=None, ylabel=None):
    plt.figure()
    plt.plot(vector)
    plt.xlabel(xlabel)
    plt.ylabel(ylabel)
    plt.plot()
    plt.savefig('static/plots/' + name)

I feel like my design is poor and there is a better way to do this. Am I right?

The rest of the code:

def allowed_file(filename):
  return '.' in filename and \
    filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/', methods=['GET', 'POST'])
def index():
  if request.method == "GET":
    return render_template('index.html', request="GET")
  else:
    if 'file' not in request.files:
      flash('No file part')
      return redirect(request.url)
    file = request.files['file']
    if file.filename == '':
      flash('No selected file')
      return redirect(request.url)
    if file and allowed_file(file.filename):
      plot_filepath = handle_file(file)
    return render_template('index.html', request="POST", filepath=plot_filepath)

The allowed_file() and majority of index() code are from the Flask docs.

\$\endgroup\$
  • \$\begingroup\$ "At some point (not visible here)" Why not? We don't mind long posts and actually prefer to see code in it's proper context. \$\endgroup\$ – Mast May 6 '17 at 19:35
  • \$\begingroup\$ It used to be in the index @app.route method (delete the file audio.png if it is there before doing anything else) but I actually removed that now, seemed like a bad thing to do. \$\endgroup\$ – pavlos163 May 6 '17 at 19:41
  • \$\begingroup\$ What also troubles me is that right now, if more than two users visit the web app and do this simultaneously, there could be an issue. Should I generate unique names for each plot and file? Seems a bit overkill. Is there an automatic way to create temp files in Flask that could do this for me? \$\endgroup\$ – pavlos163 May 6 '17 at 19:42
  • \$\begingroup\$ There isn't really that much to review here, and the code as it stands doesn't really run as we're missing secure_filename, mir?... \$\endgroup\$ – holroy May 6 '17 at 19:52
  • 1
    \$\begingroup\$ Sure! I just posted the code in mir.py and plot.py.secure_filename is imported from werkzeug.utils. The Flask docs recommended it when uploading files. \$\endgroup\$ – pavlos163 May 6 '17 at 20:02
2
\$\begingroup\$

Instead of saving file you can create io.BytesIO object and use it instead of file.

Also

    def allowed_file(filename):
      return (
          '.' in filename
          and os.splitext(filename)[1].lower() in ALLOWED_EXTENSIONS
      )

Also maybe you should check content-type header and not only extension.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.