[Java] Image upload function with Vue.js + Flask

2 minute read

Overview

This time, I will make an image recognition application using Vue.js for the front end and Flask for the back end. For the time being, this time we will implement up to the image upload function.

Environment

  • Docker
  • Vue-cli
  • flask (pipenv)

I built the environment in the above environment. See the links below for instructions and details.

Vue + Flask on Docker

Description of key points

Vue

The following code explains the details.

Home.vue


// upload image to server
    onUploadImage () {
      var params = new FormData()
      params.append('image', this.uploadedImage)
      // Post the FormData data to Flask using Axios.
      axios.post(`${API_URL}/classification`, params).then(function (response) {
        console.log(response)
    })
  1. The acquired image is Base64-encoded. “Data:image/jpeg:base64, ~”
  2. With FormData, data is converted to “key:value” format by HTTP request.
  3. Apply Axios and send data by ‘127.0.0.1:5000/classification’ + POST method.

Flask

The following code explains the details.

app.py


@app.route('/classification', methods=['POST'])
def uploadImage():
    if request.method =='POST':
        base64_png = request.form['image']
        code = base64.b64decode(base64_png.split(',')[1])
        image_decoded = Image.open(BytesIO(code))
        image_decoded.save(Path(app.config['UPLOAD_FOLDER']) /'image.png')
        return make_response(jsonify({'result':'success'}))
    else:
        return make_response(jsonify({'result':'invalid method'}), 400)
  1. “data:image/jpeg:base64, ~” exists inside FormData. Get the file name.
  2. Obtain the image with Pillow (PIL).
  3. Save the image.

Overall picture

Vue

Home.vue


<template>
  <div>
    <div class="imgContent">
      <div class="imagePreview">
        <img :src="uploadedImage" style="width:100%;" />
      </div>
      <input type="file" class="file_input" name="photo" @change="onFileChange" accept="image/*" />
      <button @click='onUploadImage'>Please judge the image...</button>
    </div>
  </div>
</template>

<script>
import axios from'axios'

const API_URL ='http://127.0.0.1:5000'
export default {
  data () {
    return {
      uploadedImage: ``
    }
  },
  methods: {
    // reflect the selected image
    onFileChange (e) {
      let files = e.target.files || e.dataTransfer.files
      this.createImage(files[0])
    },
    // display the uploaded image
    createImage (file) {
      let reader = new FileReader()
      reader.onload = (e) => {
        this.uploadedImage = e.target.result
      }
      reader.readAsDataURL(file)
    },
    // upload image to server
    onUploadImage () {
      var params = new FormData()
      params.append('image', this.uploadedImage)
      // Post the FormData data to Flask using Axios.
      axios.post(`${API_URL}/classification`, params).then(function (response) {
        console.log(response)
      })
    }
  }
}
</script>

Flask

Points to remember

  • CORS allows different origins (protocols, domains, ports) to share resources.
  • CORS is required if you have different web applications.
  • Japanese can be supported by app.config[‘JSON_AS_ASCII’] = False.

app.py


# render_template: Specify the template to reference
# jsonify: json output
from flask import Flask, render_template, jsonify, request, make_response

# CORS: Library for Ajax communication
from flask_restful import Api, Resource
from flask_cors import CORS
from random import *
from PIL import Image
from pathlib import Path
from io import BytesIO
import base64

# static_folder: specify the path of the static file built with vue
# template_folder: specify the path of index.html built with vue
app = Flask(__name__, static_folder = "./../frontend/dist/static", template_folder="./../frontend/dist")

# Japanese
app.config['JSON_AS_ASCII'] = False
# CORS=Terms for safe communication with Ajax
api = Api(app)
CORS(app)

UPLOAD_FOLDER ='./uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# Refer to index.html when receiving any request
@app.route('/', defaults={'path':''})
@app.route('/<path:path>')
def index(path):
    return render_template("index.html")

@app.route('/classification', methods=['POST'])
def uploadImage():
    if request.method =='POST':
        base64_png = request.form['image']
        code = base64.b64decode(base64_png.split(',')[1])
        image_decoded = Image.open(BytesIO(code))
        image_decoded.save(Path(app.config['UPLOAD_FOLDER']) /'image.png')
        return make_response(jsonify({'result':'success'}))
    else:
        return make_response(jsonify({'result':'invalid method'}), 400)

# app.run(host, port): Start the flask server by specifying host and port
if __name__ =='__main__':
    app.run(host='0.0.0.0', port=5000)

State

 Screenshot 2020-07-29 18.47.42.png

Like this

Very helpful

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS POST image, face detection, drawing on face with canvas