Как преобразовать данные файла в двоичные данные в React? - PullRequest
0 голосов
/ 06 мая 2020

Я реализую загрузку файла, при которой файл передается на сервер вместе с некоторыми данными. Файл и данные должны быть закодированы как данные формы.

У меня загрузка реализована двумя способами:

  1. Данные формы содержат файл как двоичную строку
  2. Данные формы содержит файл в виде обычной строки (ссылка на файл)

Первый вариант у меня работает и файл загружен успешно, а во втором случае появляется сообщение об ошибке:

«Отправленные данные не были файлом. Проверьте тип кодировки в форме.»

1. Загрузка файла с аудиофайлом в виде двоичной строки (рабочая)

Form Data
audio: (binary)
title: Some Title
content: Some content

1. Функция и форма, которые создают данные формы с аудиофайлом как двоичным (рабочий)

export class CreateStory extends Component {
  state = {
    title: "",
    content:"",
    audio:""
  };

  static propTypes = {
    addStory: PropTypes.func.isRequired
  };


// Use Ref to clear  uncontrolled file field 
constructor(props) {
    super(props);
    this.inputRef = React.createRef();
  }

 onChange = (e) => {
        if(e.target.name === 'audio') {
            this.setState({
                [e.target.name]: e.target.files[0]
            }, () => console.log(this.state.audio))

        } else {

            this.setState({
                [e.target.name]: e.target.value
            }, () => console.log(this.state))
        }
    }

onSubmit = e => {
  e.preventDefault();
  let { title, content, audio} = this.state;
  let formDataStory = new FormData(); // create form formData
  formDataStory.append('audio', audio); // add audio to formData
  formDataStory.append('title', title); // add title to formData
  formDataStory.append('content', content); // add content to formData
  console.log (this.formDataStory);
  this.props.addStory(formDataStory) // call addStory function with formDataStory as Input to create new Story
      .then(() => {
        this.setState({
          title: "", // clear title field after submission
          content:"", // clear content field after submission
        });
        this.inputRef.current.value = ''; // clear file field after submission 
      }) 
};

  render() {
    const {title, content, audio} = this.state;
    return (
      <div className="card card-body mt-4 mb-4">
        <h2>Add Story</h2>
        <form onSubmit={this.onSubmit}>

          <div className="form-group">
            <label>Title</label>
            <input
              className="form-control"
              type="text"
              name="title"
              onChange={this.onChange}
              value={title}
            />
             </div>
           <div className="form-group">
            <label>Content</label>
            <input
              className="form-control"
              type="text"
              name="content"
              onChange={this.onChange}
              value={content}
            />
          </div>

           <div className="form-group">
            <label>Audio</label>
            <input
              className="form-control"
              type="file"
              name="audio"
              onChange={this.onChange}
              ref={this.inputRef} // refer to ref

            />
          </div>

         <div className="form-group">
            <button type="submit" className="btn btn-primary">
              Submit
            </button>
          </div>
        </form>
      </div>
    );
  }
}
export default connect(
  null,
  { addStory }
)(CreateStory);

2.Загрузка файла с аудиофайлом в виде ссылки (не работает)

Form Data
audio: C:\Users\Some Link
title: Some Title
content: Some content

2.Функция и форма, которые создают данные формы с аудиофайлом в качестве ссылки (не работает)


export class EditStory extends Component {

  constructor(props) {
    super(props);
    this.getStory = this.getStory.bind(this);
    this.updateStory = this.updateStory.bind(this);
    this.onChangeTitle = this.onChangeTitle.bind(this);
    this.onChangeContent=this.onChangeContent.bind(this);
    this.onChangeAudio=this.onChangeAudio.bind(this);
    this.inputRef = React.createRef();


this.state = {
    story: {
        id: null,
        title: "",
        content: "",
        audio: ""
      }

    };
}


    componentDidMount() {
    this.getStory(this.props.match.params.id);
  }






  onChangeTitle(e) {
    const title = e.target.value;

    this.setState(prevState => ({
      story: {
        ...prevState.title,
        title: title
      }
    }), () => console.log(this.state));
  }


  onChangeContent(e) {
    const content = e.target.value;

    this.setState(prevState => ({
      story: {
        ...prevState.story,
        content: content
      }
    }), () => console.log(this.state));

  }


  onChangeAudio(e) {
const audio = e.target.name;

this.setState({
                [e.target.name]: e.target.files[0]
            }, () => console.log(this.state.audio))

        } 


 getStory(id) {
    this.props.getSingleStory(id)
      .then(response => {
        this.setState({
          story: response.data
        });

      })
      .catch(e => {
        console.log(e);
      });
  }



 updateStory() {


    let id = this.state.story.id;
    let title = this.state.story.title;
    let content = this.state.story.content;
    let audio = this.state.story.audio;
    let UpdatedData = new FormData();
    UpdatedData.append('id', id); 
    UpdatedData.append('audio', audio); // add audio to formData
    UpdatedData.append('title', title); // add title to formData
    UpdatedData.append('content', content);
    console.log (id);
    console.log (UpdatedData);
    this.props.editStory(
      id, 
      UpdatedData
    )
      .then(response => {
        console.log(response.data);
      })
      .catch(e => {
        console.log(e);
      });
  }





  static propTypes = {
      getSingleStory: PropTypes.func.isRequired,
      editStory: PropTypes.func.isRequired
  };


  render() {
    const {story} = this.state;
    return (
      <div>
        <h1>Edit {story.title}</h1>

          <div className="form-group">
            <label>Title</label>
            <input type="text" name="title" defaultValue={story.title} onChange={this.onChangeTitle} className="form-control" />
          </div>
          <div className="form-group">
            <label>Content</label>
            <textarea name="content" rows="5" defaultValue={story.content} onChange={this.onChangeContent} className="form-control" />
          </div>

     <div className="form-group">
         <label>Audio</label>
            <input
              className="form-control"
              type="file"
              name="audio"
              onChange={this.onChangeAudio}
              ref={this.inputRef} // refer to ref

            />
          </div>

          <div className="btn-group">
            <button type="submit" onClick={this.updateStory} className="btn btn-dark">Update</button>
            <button type="button"  className="btn btn-secondary">Cancel</button>
          </div>

      </div>
    );
  }
}

Я не понимаю, почему во втором случае аудиофайл не кодируется как двоичная строка. Как мне во втором случае преобразовать аудиофайл в двоичную строку и добавить их к моим данным формы?

...