Kazuaki Suzuki
Kazuaki Suzuki

Reputation: 1075

How to make a web app download mp3 file automatically [Flask on Google App Engine]

I'm a beginner in coding. I would like to make a simple web application using Google Cloud Text to Speech API.

  1. a web site with a text box
  2. you input a sentence in the text box and click a button "submit"
  3. you can download a mp3 file which is made by Google Cloud Text to Speech API

I'm an English teacher in Japan, so I would like my students to use this website to improve their English pronunciation.

Firstly, I'd like to show you my code. I use Flask on Google App Engine standard environment Python3.7.

This is directory structure.

.
├── app.yaml
├── credentials.json
├── main.py
├── requirements.txt
└── templates
    └── hello_form.html

This is main.py.

from flask import Flask
from flask import render_template
from flask import request
from flask import send_file

app = Flask(__name__)

@app.route("/", methods=['POST', 'GET'])
def index():
    if request.method == "POST":
        text = request.form['text']

        import os
        os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="credentials.json"

        from google.cloud import texttospeech
        client = texttospeech.TextToSpeechClient()
        input_text = texttospeech.types.SynthesisInput(text=text)
        voice = texttospeech.types.VoiceSelectionParams(
            language_code='en-US',
            name='en-US-Standard-C',
            ssml_gender=texttospeech.enums.SsmlVoiceGender.FEMALE)

        audio_config = texttospeech.types.AudioConfig(
            audio_encoding=texttospeech.enums.AudioEncoding.MP3)

        response = client.synthesize_speech(input_text, voice, audio_config)

        # The response's audio_content is binary.
        with open('/tmp/output.mp3', 'wb') as out:
            out.write(response.audio_content)

        return send_file("/tmp/output.mp3")
    else:
        return render_template("hello_form.html")

if __name__ == "__main__":
    app.run()

This is hello_form.html

<html>
    <head>
        <title>Sample Web Form</title>
    </head>
<body>
<h1>Fill Out This Form</h1>
<form action="/" method="POST">

    text: <input type="text" name="text">
    <br/>
    <input type="submit">
</form>
</body>
</html>

This is requirements.txt.

Flask==1.1.1
future==0.18.2
google-cloud-texttospeech==0.5.0
grpcio==1.26.0
gunicorn

This is app.yaml.

runtime: python37
entrypoint: gunicorn -b :$PORT main:app

When I deployed this app on Google App Engine, it worked pretty well. However, I couldn't download a mp3 file directly. I show you what I mean.

Step1: If I enter my app's URL on browser(Google Chrome on Windows10), I see this simple form. form Step2: I input a text and push "submit". submit

Step3: Server send mp3 file to client, but download doesn't start. download1

Step4: Right click on browser and push "Save as". save_as

Step5: Download manager begin to work and name mp3 file. download2

Step6: Download mp3 file to the local download folder. download3

I don't need Step3 and 4. When I push "submit", I want the browser to launch download manager automatically.

Could you give me any information or suggestion?

Thank you in advance.

Sincerely, Kazu


Thanks to Cameron Roberts, I overcomed my difficulty.

Passing 'as_attachment=True' to send_file solved the problem.

However, now I face another problem. This solution worked perfectly when I accessed my web app from PC(Google Chrome). But when I accessed my web app from iPhone(Google Chrome), download doesn't start. It's a big problem for me because on iPhone I can't right click and do "Save as" operation.

This is a screenshot.

enter image description here

Could you give me any information or suggestion?

Thank you in advance.

Sincerely, Kazu

Upvotes: 2

Views: 3584

Answers (1)

Cameron Roberts
Cameron Roberts

Reputation: 7387

You must set the 'content-disposition' of the file to 'attachment'. With flask, you can achieve this by passing 'as_attachment=True' to send file.

return send_file("/tmp/output.mp3",as_attachment=True)

The flask documentation states:

as_attachment – set to True if you want to send this file with a Content-Disposition: attachment header.

https://flask.palletsprojects.com/en/1.1.x/api/#flask.send_file

Upvotes: 3

Related Questions