Я реализую загрузку файла, при которой файл передается на сервер вместе с некоторыми данными. Файл и данные должны быть закодированы как данные формы.
У меня загрузка реализована двумя способами:
- Данные формы содержат файл как двоичную строку
- Данные формы содержит файл в виде обычной строки (ссылка на файл)
Первый вариант у меня работает и файл загружен успешно, а во втором случае появляется сообщение об ошибке:
«Отправленные данные не были файлом. Проверьте тип кодировки в форме.»
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>
);
}
}
Я не понимаю, почему во втором случае аудиофайл не кодируется как двоичная строка. Как мне во втором случае преобразовать аудиофайл в двоичную строку и добавить их к моим данным формы?