处理上传到 Cloudinary 的空图像字段
Handle empty image field upload to Cloudinary
在这个项目中,我有一个带有 input type='file'
的 Redux 表单,用于将图像上传到 Cloudinary 以及将其他数据上传到 MongoLab。该表单与项目 (Book
) 创建组件 (booklist\client\src\components\AddBook.js) 和用于编辑 Book
(booklist\client\src\components\Book.js).[=30= 的组件重用]
AddBookForm
形式。 book
属性来自父 Book
组件。其他Field
被省略了。
class AddBookForm extends Component {
componentDidMount() {
this.handleInitialize();
}
handleInitialize() {
let names = '';
if (this.props.book) {
const authors = this.props.book.authors && this.props.book.authors.map(ath => {
let str = `${ath.firstname} ${ath.lastname}, `;
names = names + str;
});
names = names.slice(0, -2);
}
const initData = {
'title': this.props.book && this.props.book.title || '',
'pages': this.props.book && this.props.book.pages || 0,
'publisher': this.props.book && this.props.book.publisher || '',
'publishedAt': this.props.book && moment(this.props.book.publishedAt).format('MM.DD.YYYY') || '',
'releasedAt': this.props.book && moment(this.props.book.releasedAt).format('MM.DD.YYYY') || '',
'isbn13': this.props.book && this.props.book.isbn13 || '',
'cover': this.props.book && this.props.book.cover || '',
'authors': names,
book_id: this.props.book && this.props.book._id,
cloudinarySecureUrl: this.props.book && this.props.book.cloudinarySecureUrl
};
this.props.initialize(initData);
}
render() {
const { onSubmit, handleSubmit, pristine, reset, submitting } = this.props;
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Field
name='cover'
type='file'
component={fileField}
label='Cover'
comment='Please provide a cover. Optional'
/>
<button
disabled={submitting}
className='add-form-action'
>
Add Book
</button>
<button type='button' disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</form>
)
}
export default AddBookForm = reduxForm({
form: 'AddBookForm'
})(AddBookForm);
处理表单提交的Book
组件方法
onSubmit(formData) {
const authors = formData.authors;
const authorsToArray = [];
const authorsArray = authors.split(',');
for (let ath of authorsArray) {
const firstname = ath.trim().split(' ')[0];
const lastname = ath.trim().split(' ')[1] || '';
authorsToArray.push({
firstname,
lastname
});
}
formData.authors = authorsToArray;
this.props.addBook(formData, this.props.history);
}
这是处理 Book
表单数据上传的 addBook()
操作。
export const addBook = (bookData, history) => (dispatch) => {
const cloudinaryUrl = 'https://api.cloudinary.com/v1_1/*******/upload';
const cloudinaryUploadPreset = '*******';
const formData = new FormData();
formData.append('file', bookData.cover[0]);
formData.append('upload_preset', cloudinaryUploadPreset);
axios({
url: cloudinaryUrl,
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: formData
})
.then(res => {
bookData.cloudinarySecureUrl = res.data.secure_url;
axios.post('/api/books', bookData)
.then(res => {
history.push('/')
})
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
}));
})
.catch(error => console.log('Cloudinary image upload error:', error.message));
};
我默认 bookData.cover[0]
是什么,这样我就可以为 Field name='cover'
提交没有图像的表单?难道there/should我走别的路?完整的回购在 https://github.com/ElAnonimo/booklist
更新
在 addBook()
操作的 catch
子句中添加了编辑 Book
时不上传图像的操作,我得到了正确的图书列表,即使图像仍然存在图片上传时。
.catch(error => {
history.push('/');
});
这就是我在书创作行动中所做的。
// add book
export const addBook = (bookData, history) => (dispatch) => {
const cloudinaryUrl = 'https://api.cloudinary.com/v1_1/dlzbcvsbf/upload';
const cloudinaryUploadPreset = 'hvqidzpj';
const formData = new FormData();
// bookData.cover is the `FileList` array created when user submits a cover picture, bookData.cover[0] is the actual cover picture file
bookData.cover && bookData.cover[0] && formData.append('file', bookData.cover[0]);
formData.append('upload_preset', cloudinaryUploadPreset);
if (!bookData.cover[0]) {
axios.post('/api/books', bookData)
.then(res => {
history.push('/')
})
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
}));
} else {
axios({
url: cloudinaryUrl,
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: formData
})
.then(res => {
// book cover isn't stored in the DB no need to send it to backend
delete bookData.cover;
bookData.cloudinarySecureUrl = res.data.secure_url;
axios.post('/api/books', bookData)
.then(res => {
history.push('/')
})
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
}));
})
.catch(error => {
console.log('Cloudinary image upload error:', error.message);
history.push('/');
});
}
};
在这个项目中,我有一个带有 input type='file'
的 Redux 表单,用于将图像上传到 Cloudinary 以及将其他数据上传到 MongoLab。该表单与项目 (Book
) 创建组件 (booklist\client\src\components\AddBook.js) 和用于编辑 Book
(booklist\client\src\components\Book.js).[=30= 的组件重用]
AddBookForm
形式。 book
属性来自父 Book
组件。其他Field
被省略了。
class AddBookForm extends Component {
componentDidMount() {
this.handleInitialize();
}
handleInitialize() {
let names = '';
if (this.props.book) {
const authors = this.props.book.authors && this.props.book.authors.map(ath => {
let str = `${ath.firstname} ${ath.lastname}, `;
names = names + str;
});
names = names.slice(0, -2);
}
const initData = {
'title': this.props.book && this.props.book.title || '',
'pages': this.props.book && this.props.book.pages || 0,
'publisher': this.props.book && this.props.book.publisher || '',
'publishedAt': this.props.book && moment(this.props.book.publishedAt).format('MM.DD.YYYY') || '',
'releasedAt': this.props.book && moment(this.props.book.releasedAt).format('MM.DD.YYYY') || '',
'isbn13': this.props.book && this.props.book.isbn13 || '',
'cover': this.props.book && this.props.book.cover || '',
'authors': names,
book_id: this.props.book && this.props.book._id,
cloudinarySecureUrl: this.props.book && this.props.book.cloudinarySecureUrl
};
this.props.initialize(initData);
}
render() {
const { onSubmit, handleSubmit, pristine, reset, submitting } = this.props;
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Field
name='cover'
type='file'
component={fileField}
label='Cover'
comment='Please provide a cover. Optional'
/>
<button
disabled={submitting}
className='add-form-action'
>
Add Book
</button>
<button type='button' disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</form>
)
}
export default AddBookForm = reduxForm({
form: 'AddBookForm'
})(AddBookForm);
处理表单提交的Book
组件方法
onSubmit(formData) {
const authors = formData.authors;
const authorsToArray = [];
const authorsArray = authors.split(',');
for (let ath of authorsArray) {
const firstname = ath.trim().split(' ')[0];
const lastname = ath.trim().split(' ')[1] || '';
authorsToArray.push({
firstname,
lastname
});
}
formData.authors = authorsToArray;
this.props.addBook(formData, this.props.history);
}
这是处理 Book
表单数据上传的 addBook()
操作。
export const addBook = (bookData, history) => (dispatch) => {
const cloudinaryUrl = 'https://api.cloudinary.com/v1_1/*******/upload';
const cloudinaryUploadPreset = '*******';
const formData = new FormData();
formData.append('file', bookData.cover[0]);
formData.append('upload_preset', cloudinaryUploadPreset);
axios({
url: cloudinaryUrl,
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: formData
})
.then(res => {
bookData.cloudinarySecureUrl = res.data.secure_url;
axios.post('/api/books', bookData)
.then(res => {
history.push('/')
})
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
}));
})
.catch(error => console.log('Cloudinary image upload error:', error.message));
};
我默认 bookData.cover[0]
是什么,这样我就可以为 Field name='cover'
提交没有图像的表单?难道there/should我走别的路?完整的回购在 https://github.com/ElAnonimo/booklist
更新
在 addBook()
操作的 catch
子句中添加了编辑 Book
时不上传图像的操作,我得到了正确的图书列表,即使图像仍然存在图片上传时。
.catch(error => {
history.push('/');
});
这就是我在书创作行动中所做的。
// add book
export const addBook = (bookData, history) => (dispatch) => {
const cloudinaryUrl = 'https://api.cloudinary.com/v1_1/dlzbcvsbf/upload';
const cloudinaryUploadPreset = 'hvqidzpj';
const formData = new FormData();
// bookData.cover is the `FileList` array created when user submits a cover picture, bookData.cover[0] is the actual cover picture file
bookData.cover && bookData.cover[0] && formData.append('file', bookData.cover[0]);
formData.append('upload_preset', cloudinaryUploadPreset);
if (!bookData.cover[0]) {
axios.post('/api/books', bookData)
.then(res => {
history.push('/')
})
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
}));
} else {
axios({
url: cloudinaryUrl,
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: formData
})
.then(res => {
// book cover isn't stored in the DB no need to send it to backend
delete bookData.cover;
bookData.cloudinarySecureUrl = res.data.secure_url;
axios.post('/api/books', bookData)
.then(res => {
history.push('/')
})
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
}));
})
.catch(error => {
console.log('Cloudinary image upload error:', error.message);
history.push('/');
});
}
};