Upload an Image and Display it back as a response using Flask
Asked Answered
U

2

8

I'm a beginner in front end development, and have to do a small web app in Flask for a project.

I have written a Flask app that lets you upload an image using HTML Forms and then displays the image back to the user when you hit Upload. I need to modify this such that the image does not get saved to a folder in the project directory everytime a user uploads it. Basically, the app should send the uploaded image back in the body of the response.

Here is my code so far:

UploadTest.py

import os


from uuid import uuid4

from flask import Flask, request, render_template, send_from_directory

app = Flask(__name__)
# app = Flask(__name__, static_folder="images")



APP_ROOT = os.path.dirname(os.path.abspath(__file__))

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

@app.route("/upload", methods=["POST"])
def upload():
    target = os.path.join(APP_ROOT, 'images/')
    print(target)
    if not os.path.isdir(target):
            os.mkdir(target)
    else:
        print("Couldn't create upload directory: {}".format(target))
    print(request.files.getlist("file"))
    for upload in request.files.getlist("file"):
        print(upload)
        print("{} is the file name".format(upload.filename))
        filename = upload.filename
        destination = "/".join([target, filename])
        print ("Accept incoming file:", filename)
        print ("Save it to:", destination)
        upload.save(destination)

    return render_template("complete.html", image_name=filename)

@app.route('/upload/<filename>')
def send_image(filename):
    return send_from_directory("images", filename)

if __name__ == "__main__":
    app.run(port=8080, debug=True)

upload.html - creates an upload form

<!DOCTYPE html>
<html>
<head>
<title>Upload</title>
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
</head>
<body>

<form id="upload-form" action="{{ url_for('upload') }}" method="POST" enctype="multipart/form-data">

    <strong>Files:</strong><br>
    <input id="file-picker" type="file" name="file" accept="image/*" multiple>
    <div id="msg"></div>
    <input type="submit" value="Upload!" id="upload-button">
</form>
</body>
<script>

    $("#file-picker").change(function(){

        var input = document.getElementById('file-picker');

        for (var i=0; i<input.files.length; i++)
        {

            var ext= input.files[i].name.substring(input.files[i].name.lastIndexOf('.')+1).toLowerCase()

            if ((ext == 'jpg') || (ext == 'png'))
            {
                $("#msg").text("Files are supported")
            }
            else
            {
                $("#msg").text("Files are NOT supported")
                document.getElementById("file-picker").value ="";
            }

        }


    } );

</script>
</html>

complete.html - displays the image from the folder in which it has been saved after a user hits "upload"

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
Uploaded
<img src=" {{url_for('send_image', filename=image_name)}}">
</body>
</html>

I have tried researching quite a bit but was unable to find anything other than deleting the folder after it has been displayed (which I didn't think is the right way of solving the question at hand). I'd really appreciate any help in this matter, and if there is a better solution than what my code currently does, I'd love to learn more!

Thank you! :)

Unclad answered 16/3, 2017 at 4:12 Comment(3)
The user is sending many files. Do you want to send only one image back or send many?Nitrosyl
But my code only displays the last file that was uploaded. I need to send only one image at a time, but I want to be able to go back and upload another image again @LaraChicharoUnclad
I have the same question. Two years has gone and we still don't have the answer?Trommel
S
2

Please check below code can help you.Copy the below code in upload.html in templates folder.

<!DOCTYPE html>

<html>
<head>
<link class="jsbin" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.0/jquery-ui.min.js"></script>
<meta charset=utf-8 />

 <script src="{{ url_for('static', filename='upload.js') }}"></script>

<style>
  article, aside, figure, footer, header, hgroup, 
  menu, nav, section { display: block; }
</style>
</head>
<body>
<form action = "http://127.0.0.1:5000/uploader" method = "POST" 
 enctype = "multipart/form-data">
  <input type='file' name = 'file' onchange="readURL(this);" />
    <img id="blah" src="#" alt="your image" />
 <input type = "submit"/>
</form>
</body>
</html>

Copy the below code in upload.js file in static folder

function readURL(input) {
if (input.files && input.files[0]) {
    var reader = new FileReader();

    reader.onload = function (e) {
        $('#blah')
            .attr('src', e.target.result)
            .width(150)
            .height(200);
    };

    reader.readAsDataURL(input.files[0]);
}
}

Now copy the below code in a python file

from flask import Flask, render_template, request
from werkzeug import secure_filename
import os 

app = Flask(__name__)

app.config['UPLOAD_FOLDER'] = 'D:/Projects/flask/image_upload/images/'

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

@app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
   if request.method == 'POST':
      f = request.files['file']
      f.save(os.path.join(app.config['UPLOAD_FOLDER'],secure_filename(f.filename)))
      return 'file uploaded successfully'

# if __name__ == '__main__':
app.run(debug = True)

Above piece of code will help you to browse and display the image on html page and as well save the image on your disk at desired location.

Spa answered 12/10, 2019 at 13:50 Comment(0)
C
0

If you want to send back image to client there's 2 approach,

  1. You can send image to client as an file url
  2. You need to convert an image as blob or base64 image and show image
Covenanter answered 6/6, 2021 at 6:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.