2

I'm trying to send an image file(that resides locally) from my react single page frontend app to my flask backend. Some of the things I have tried out but not limited to are capturing my content type and indicating the encType on the front end. Although, the post requests indicates that it was successful. However, when I log the requests.files, request.form, request.values, I get no data input. Obviously, there's something I'm missing out and could really use any help I could get from anyone. Thanks

FrontEnd:

import React, { Component } from 'react';
import axios from 'axios';
import logo from './logo.svg';
import './App.css';
// const qs = require('querystring');

class App extends Component {
  constructor(props){
    super();
    this.state = { imagePreviewUrl: '', file: '' };

    this._handleSubmit = this._handleSubmit.bind(this);
    this._handleImageChange = this._handleImageChange.bind(this);
    this.uploadImage = this.uploadImage.bind(this);
  }

  _handleImageChange(e){
    e.preventDefault();
    let file = e.target.files[0];
    let reader = new FileReader();
    reader.onloadend = () => {
      this.setState({ file: file,
                      imagePreviewUrl: reader.result });
    }
    reader.readAsDataURL(file);
  }

  _handleSubmit(e){
    e.preventDefault();
    console.log("file value before this.uploadImage call:",this.state.file);
    this.uploadImage(this.state.file);

  }

  uploadImage(filepath){

      let imageFormData = new FormData();
      imageFormData.append('filepath', filepath, filepath.name);
      let newHeaders = new Headers({
              "Content-type": "image/png"
            });
      console.log("checking if imageFormData has value:",imageFormData.has('filepath'));
        return axios.post('/add', newHeaders, imageFormData)
          .then((response) => {
            console.log("response:", response);
          })
          .catch((err) => {
            console.log("error:", err);
          });

    }


  render() {

    let { imagePreviewUrl } = this.state;
    let $imagePreview = null
    if (imagePreviewUrl){
      $imagePreview = ( <img src={imagePreviewUrl} />);
    }
    else {
      $imagePreview = (<div className="previewText">Please select an Image for Preview</div>);
    }
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <form onSubmit={this._handleSubmit}>
          <div>
            <label htmlFor="image_uploads">Choose images to upload (PNG, JPG)</label>
            <input type="file" id="image_uploads" name="filepath" encType="multipart/form-data" onChange={this._handleImageChange}/>
          </div>
          <div>
            <button type='submit'>Submit</button>
          </div>
        </form>
        <div>
        {$imagePreview}
        </div>
      </div>
    );
  }
}

export default App;

Backend:

from flask import Flask, request, render_template, send_from_directory

gunicorn_error_logger = logging.getLogger('gunicorn.error')
app.logger.handlers.extend(gunicorn_error_logger.handlers)
app.logger.setLevel(logging.DEBUG)
app = Flask(__name__)


@app.route('/', methods=['GET'])
def root():
    app.logger.debug("Inside root route")
    return render_template('index.html')

@app.route('/add', methods=['POST'])
def add_handler():
    app.logger.debug("Inside add route")
    app.logger.debug("Request Params: {}".format(request))
    app.logger.debug("Values: {}".format(request.values))
    app.logger.debug("Form: {}".format(request.form))
    app.logger.debug("Files: {}".format(request.files))

    return "got it"
dlvr
  • 93
  • 1
  • 11
  • Same kind of issue for me. it request.data has data, but do not know how to retrieve it (in my case, i have several parts) – blackbox Mar 31 '18 at 08:11

2 Answers2

1

I had the same kind of issue trying to send a sound blob to the server. Data is received and can be seen by calling request.get_data() if you call only this method on request (see : https://stackoverflow.com/a/23898949/1058203). However, I found no easy way to parse this data in a correct way. What worked for me :

First convert blob to base64 on client, and ship to server as Json :

var reader = new FileReader();
reader.readAsDataURL(blob); 
reader.onloadend = function() {
  var base64audio = reader.result;
  // may not apply or differ in your case
  var prefixToDrop = 'data:audio/wav;base64,';
  var base64audioCut = base64audio.substring(prefixToDrop.length);
  callbackFn(base64audioCut)
};

Ship to backend in callback using JQuery :

$.ajax({
        type: 'POST',
        url: '/receiveAudio',
        data: JSON.stringify({
          "type": "wav",
          "base64audio" : base64audioCut
        }),
        dataType:"json",
        processData: false,
        contentType: "application/json;",
        success: function(x){...},
        error: function(x){...},
        processData: false
});

Backend :

@app.route('/receiveAudio', methods=['POST'])
def receiveAudio():
    dataKey = 'base64audio'
    json = request.get_json()

    if not dataKey in json:
        return abort(400, "Missing 'base64audio' key")

    base64_decoded = base64.b64decode(json[dataKey])
blackbox
  • 671
  • 6
  • 18
0

Call File Upload from React

   function onFileUpload(event){
        const fileblob = new Blob([event.target.files[0]], { type: 'image/png' });// WORKS much better (if you know what MIME type you want.
        let data = new FormData();
        data.append('file', imageBlob);
        return axios
            .post(`http://localhost:3030/imagerecog`, data, {
                headers: {
                    'Content-Type': 'multipart/form-data',
                },
            })
            .then(res => {
                console.log(res)
                return res
        });
    }

Python API Install Pillow module

py -m pip install Pillow

Use the module to show or save the file from the blob

@app.route('/imagerecog', methods = ['GET', 'POST'])
def imagerecog():
   if request.method == 'POST':
      print("Recieved Image File")
      file = request.files['file']
      print('File from the POST request is: {}'.format(file))
      img = Image.open(file.stream)
      # img.show()
      img.save("recogImage.jpg")
      return "Success"
   return 'Call from get'
Sarat Chandra
  • 5,636
  • 34
  • 30