使用react.js组件中的Dropzone上传文件到sails.js中的后端

时间:2016-07-02 01:49:14

标签: reactjs upload sails.js dropzone.js multipart

我的应用后端使用sails.js,并且有一个API api/question/new用于创建新问题。此API支持使用skipper模块here上传文件或图片,我已验证在REST客户端PostMan中使用文件字段进行上传以及文本字段titlecontenttags

现在,我正在尝试使我的基于react.js的组件(问题表单)同时发布文本和上传文件。我遇到了一个名为react-dropzone here的好库,我正在尝试将其与我的表单集成。 react.js中的表单由saga函数处理,以便使用whatwg-fetch library进行发布。

问题表单组件:

export const fields = ['title', 'content', 'tags', 'images'];

const validate = values => {
    const errors = {};
    if (!values.title) {
        errors.title = 'Required';
    }
    if (!values.content) {
        errors.content = 'Required';
    } else if (values.content.length < 2) { // TODO: specify a constant for length of content
        errors.content = 'Question is too short';
    }

    return errors;
}

class QuestionForm extends React.Component {

    constructor(props, context) {
        super(props, context);
        this.dropFile = this.onDrop.bind(this);
    }

    onDrop(files) {
        console.log('received files: ', files);
        this.props.fields.images = [];
        files.forEach((file) => {
            this.props.fields.images.push(file);
        });
    }

  render() {
      const { fields: {title, content, tags, images}, resetForm, handleSubmit, submitting, pristine} = this.props;
    return (
      <div className={ styles.QuestionForm }>
          <form onSubmit={handleSubmit}>
              <Row>
                  <label>Title</label>
                  <div>
                      <input className="form-control" type="text" maxlength="100" placeholder="Title" {...title} name="title" />
                  </div>
                  {title.touched && title.error && <div>{title.error}</div>}
              </Row>
              <Row>
                  <label>Content</label>
                  <div>
                      <input className="form-control" type="text" maxlength="100" placeholder="Content" {...content} name="content" />
                  </div>
                  {content.touched && content.error && <div>{content.error}</div>}
              </Row>
              <Row>
                  <label>Tags</label>
                  <div>
                      <input className="form-control" type="text" maxlength="100" placeholder="Tags" {...tags} name="content" />
                  </div>
              </Row>
              <Row>
                   <Dropzone onDrop={this.dropFile}>
                      <div>Try dropping some files here, or click to select files to upload.</div>
                    </Dropzone>
              </Row>
              <Row>
                  <label></label>
                  <button className="btn btn-warning" type="button" disabled={pristine || submitting} onClick={resetForm}>Clear Values</button>
                  <button className="btn btn-primary" type="submit" disabled={pristine || submitting}>Submit</button>
              </Row>
          </form>
      </div>
    );
  }
}

以下是使用whatwg-fetch发布表单数据的传奇功能:

export function* askQuestion() {
    while(true) {
        const action = yield take(types.SUBMIT_QUESTION);
        let askQUrl = 'http://localhost:1337/api/question/new';
        const curToken = getJwtToken();
        var formData = new FormData();

        action.questionObj.images.forEach(function(img) {
            formData.append('images', img);
        });

        formData.append('title', action.questionObj.title);
        formData.append('content', action.questionObj.content);
        formData.append('tags', action.questionObj.tags);
        console.info('formData: ', formData); // here the images field shows as undefined
        try {
            let options = {
                method: 'POST',
                headers: {
                    'Content-Type': 'multipart/form-data'
                },
                // body: JSON.stringify(action.questionObj),
                body: formData,
            };
            const response = yield call(request, askQUrl, options);
            if (response.data) {
                yield put(submitQuestionSuccess(response.data));
            } else {
                yield put(submitQuestionFailed(response.error));
            }
        } catch(e) {
            yield put(submitQuestionFailed('server problem in taking your question'));
        }
    }
}

当我提交带有title / content / tags和文件的表单时,我在浏览器控制台中收到以下错误:

  

在askQuestion中没有被捕获TypeError:无法读取属性'forEach'   未定义

我不确定为什么action.questionObj.images未定义,因为在dropFile()函数中,我将文件推送到images数组中。谁能发现我做错了什么?或者有更好的方法将文本和文件同时发布到基于sails.js的后端吗?

0 个答案:

没有答案