无法提取Flask后端上React前端上传的图像文件

时间:2017-08-11 18:37:44

标签: python reactjs flask http-headers mxhr

我试图从我的反应单页前端应用程序向我的烧瓶后端发送一个图像文件(本地驻留)。我尝试但不限于的一些事情是捕获我的内容类型并在前端指示encType。虽然,帖子请求表明它是成功的。但是,当我记录requests.files,request.form,request.values时,我没有输入任何数据。显然,我错过了一些东西,可以真正使用我从任何人那里得到的任何帮助。感谢

前端

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;

后端

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"

2 个答案:

答案 0 :(得分:0)

我尝试将声音blob发送到服务器时遇到了同样的问题。如果您仅根据请求调用此方法,则可以通过调用request.get_data()来接收数据并进行查看(请参阅:https://stackoverflow.com/a/23898949/1058203)。 但是,我发现没有简单的方法以正确的方式解析这些数据。 什么对我有用:

首先在客户端将blob转换为base64,然后将其作为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)
};

使用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
});

后端:

@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])

答案 1 :(得分:0)

从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 安装枕头模块

py -m pip install Pillow

使用该模块显示或保存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'