Я создаю приложение для рецептов и в настоящее время работаю над тем, чтобы пользователь мог загружать свои собственные рецепты. У меня есть форма с различными полями ввода, и одним из них является загрузка изображений. Вот как моя форма выглядит в методе render ():
render() {
return <div>
<h2>
Share Your Culinary Art
</h2>
<form method="post" onSubmit = {
e => this.submitRecipe(e)
}>
<div>
<label htmlFor="name">Recipe Name *</label>
<input name="name" onInput = { e => { this.handleChange(e)}} required />
</div>
<div>
<label htmlFor="cuisine">Cuisine</label>
<input name="cuisine" onInput = { e => { this.handleChange(e)}}/>
</div>
<div>
<label htmlFor="ingredients" required>Ingredients*</label> <br />
<textarea name="ingredients" rows='10' columns='30' placeholder="Ingredients separated by commas" onInput = { e => { this.handleChange(e)}}/>
</div>
<div>
<label htmlFor="instructions">Instructions *</label> <br />
<textarea name="instructions" rows='10' columns='30' onInput = { e => { this.handleChange(e)}} required/>
</div>
<div>
<label htmlFor="image">Choose your recipe image:</label>
<!-- below is problematic area-->
<input type="file" name="file" onChange= { e => {this.onChangeImageHandler(e)} } />
</div>
<button>Reset</button>
<button>Upload</button>
</form>
</div>
}
Все поля ввода (кроме файла один) присоединены к функции handleChange (), которая, в свою очередь, вызывает функцию handleInputChange (), которая выглядит следующим образом в том же файле:
handleChange = e => {
e.preventDefault();
this.handleInputChange(e.target.name, e.target.value);
}
handleInputChange = (key, value) => {
this.setState({
uploadRecipesFormData: {
_id: uuidv4(),
...this.state.uploadRecipesFormData,
addedBy: 'guest',
[key]: value
}
});
}
Вместо этого загрузка изображения присоединяется к функции onChangeImageHandler:
onChangeImageHandler = e => {
this.setState({
selectedFile: e.target.files[0]
});
}
Когда пользователь нажимает кнопку «Загрузить», запускается функция submitRecipe, которая затем запускает функцию uploadRecipe. Оба определены ниже:
submitRecipe = e => {
e.preventDefault();
this.uploadRecipe();
}
uploadRecipe = () => {
console.log(this.state.selectedFile);
const imageData = new FormData();
imageData.append('file', this.state.selectedFile);
this.setState({
uploadRecipesFormData : {
...this.state.uploadRecipesFormData,
imageData
}
})
axios.post(`http://localhost:3000/recipes`, this.state.uploadRecipesFormData)
.then(res => alert(res.data))
.catch(err => console.error(err));
}
Для полноты картины весь файл показан ниже:
import React from 'react';
import axios from 'axios';
import { v4 as uuidv4 } from 'uuid';
export default class UploadRecipes extends React.Component {
constructor(props) {
super(props);
this.state = {
uploadRecipesFormData: {},
selectedFile: null
};
}
uploadRecipe = () => {
console.log(this.state.selectedFile);
const imageData = new FormData();
imageData.append('file', this.state.selectedFile);
this.setState({
uploadRecipesFormData : {
...this.state.uploadRecipesFormData,
imageData
}
})
axios.post(`http://localhost:3000/recipes`, this.state.uploadRecipesFormData)
.then(res => alert(res.data))
.catch(err => console.error(err));
}
onChangeImageHandler = e => {
this.setState({
selectedFile: e.target.files[0]
});
}
handleChange = e => {
e.preventDefault();
this.handleInputChange(e.target.name, e.target.value);
}
handleInputChange = (key, value) => {
this.setState({
uploadRecipesFormData: {
_id: uuidv4(),
...this.state.uploadRecipesFormData,
addedBy: 'guest',
[key]: value
}
});
}
submitRecipe = e => {
e.preventDefault();
this.uploadRecipe();
}
render() {
return <div>
<h2>
Share Your Culinary Art
</h2>
<form method="post" onSubmit = {
e => this.submitRecipe(e)
}>
<div>
<label htmlFor="name">Recipe Name *</label>
<input name="name" onInput = { e => { this.handleChange(e)}} required />
</div>
<div>
<label htmlFor="cuisine">Cuisine</label>
<input name="cuisine" onInput = { e => { this.handleChange(e)}}/>
</div>
<div>
<label htmlFor="ingredients" required>Ingredients*</label> <br />
<textarea name="ingredients" rows='10' columns='30' placeholder="Ingredients separated by commas" onInput = { e => { this.handleChange(e)}}/>
</div>
<div>
<label htmlFor="instructions">Instructions *</label> <br />
<textarea name="instructions" rows='10' columns='30' onInput = { e => { this.handleChange(e)}} required/>
</div>
<div>
<label htmlFor="image">Choose your recipe image:</label>
<input type="file" name="file" onChange= { e => {this.onChangeImageHandler(e)} } />
</div>
<button>Reset</button>
<button>Upload</button>
</form>
</div>
}
}
Проблема, с которой я сталкиваюсь, заключается в том, что мой переданный файл не отображается должным образом в инструментах React dev:
И когда я проверяю журнал консоли непосредственно перед запуском загрузки, где я использую FormData для прикрепления файла, я вижу, что он регистрируется:
File {name: "chicken-curry.jpg", lastModified: 1584878531812, lastModifiedDate: Sun Mar 22 2020 08:02:11 GMT-0400 (Eastern Daylight Time), webkitRelativePath: "", size: 344292, …}
name: "chicken-curry.jpg"
lastModified: 1584878531812
lastModifiedDate: Sun Mar 22 2020 08:02:11 GMT-0400 (Eastern Daylight Time) {}
webkitRelativePath: ""
size: 344292
type: "image/jpeg"
__proto__: File
Однако в отправляемых заголовках запроса я не вижу атрибута файла или каких-либо данных, указывающих c на файл:
Я просто не могу понять как я должен передавать данные этого файла вместе с другими полями.