【发布时间】:2019-05-09 04:30:47
【问题描述】:
我被一个问题困扰了大约 2 天。我可能正在寻找,但我找不到关于它的帖子...
因此,我将 Ruby on Rails 框架与 gem react on rails 结合使用,并尝试使用 CarrierWave gem 在 react 中进行多次上传。
因此,当只有一个文件时,上传效果非常好。但我采用了另一种策略,结果我最终不得不为单个模型上传多个文件。所以我创建了一个多态模型(如果我在其他地方需要它,它更通用)。
所以问题是我将数据从 react 发送到我的控制器的那一刻。确实 JSON.stringify 不适用于对象文件,我不明白我该怎么做......
我的控制器
# POST /band_musics
# POST /band_musics.json
def create
@band_music = BandMusic.new({
:name => band_music_params[:name],
:phone => band_music_params[:phone],
:mail => band_music_params[:mail],
:style => band_music_params[:style],
:comment => band_music_params[:comment],
:status => band_music_params[:status],
:musics_attributes => JSON.parse(band_music_params[:musics_attributes]),
:youtubes_attributes => JSON.parse(band_music_params[:youtubes_attributes])
})
respond_to do |format|
if @band_music.save
format.html { redirect_to root_path, notice: 'Le groupe a bien été enregisté' }
format.json { render :show, status: :created, location: @band_music }
else
format.html { render :new }
format.json { render json: @band_music.errors, status: :unprocessable_entity }
end
end
end
我的 band_music_params
def band_music_params
params.require(:band_music).permit(:name, :mail, :phone, :style, :comment, :status, :youtubes_attributes, :musics_attributes)
end
我的反应组件
import PropTypes from 'prop-types';
import React from 'react';
import ReactDropzone from 'react-dropzone'
export default class GroupForm extends React.Component {
static propTypes = {
};
/**
* @param props - Comes from your rails view.
*/
constructor(props) {
super(props);
this.state = {
files: {},
loading: false,
disabled: true,
};
}
submitGroupForm = (event) => {
event.preventDefault();
let response_files = {}
Object.keys(this.state.files).map((file, index) => {
response_files[index] = {
'lastMod' : this.state.files[file].sound.lastModified,
'lastModDate': this.state.files[file].sound.lastModifiedDate,
'name' : this.state.files[file].sound.name,
'size' : this.state.files[file].sound.size,
'type' : this.state.files[file].sound.type,
}
});
const file_array = JSON.stringify(response_files);
this.setState({ loading: true });
let formPayLoad = new FormData();
formPayLoad.append('band_music[musics_attributes]', file_array);
fetch(this.props.url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'X-CSRF-Token': ReactOnRails.authenticityToken(),
},
body: formPayLoad,
}).then((response) => {
console.log(response)
});
}
onDrop = (files) => {
if (Object.keys(this.state.files).length === 3) return
var countFile = Object.keys(this.state.files).length
console.log(countFile)
files.forEach(file => {
let hash = this.state.files
hash[`${countFile}`] = { sound: file }
this.setState({
files: hash
});
});
}
render() {
console.log(this.state)
return (
<div>
<form onSubmit={this.submitGroupForm}>
<div className="form-group">
<label htmlFor="sound" className="color-primary">
Fichier(s) Audio(s)
</label>
<ReactDropzone
accept="audio/*"
onDrop={this.onDrop}
className="react-drop-zone-css"
>
{ Object.keys(this.state.files).length > 0 &&
<div className="fileContainer">
{Object.keys(this.state.files).map((file) => (
<p className="file">
<i className="fa fa-music fa-2x mb-2"></i>
{this.state.files[file].sound.name}
</p>
))}
{ Object.keys(this.state.files).length < 1 &&
<p className="plus">
<i className="fa fa-plus fa-3x mb-2"></i>
</p>
}
</div>
}
{ Object.keys(this.state.files).length === 0 &&
<div className="d-flex justify-content-center align-items-center w-100 h-100">
<p className="mb-0">Cliquez pour importer un fichier audio ! (3 fichiers max)</p>
</div>
}
</ReactDropzone>
</div>
<div className="row justify-content-center">
{
!!this.state.loading ? (
<input className="btn btn-lg bg-button color-white mt-3" type="submit" value="Chargement... Cette action peut prendre quelques minutes" />
) : (
<input className={"btn btn-lg bg-button color-white mt-3 " + (!!this.state.disabled ? 'disabled' : '')} disabled={!!this.state.disabled} type="submit" value="S'inscrire au tremplin" />
)
}
</div>
</form>
</div>
);
}
}
为了简单起见,如何在参数中传递文件。在这里,我尝试将文件转换为 stringify 的经典对象,它不会出错,但不会将文件保存在多态模型中...
如果您需要我发布另一个文件以获得更多理解,请在评论中说出来,提前谢谢您:)
【问题讨论】:
-
在处理实际上传时,如果可以的话,您可能希望使用ActiveStorage 而不是 CarrierWave - 它非常容易处理文件参数,您可以使用 API 进行直接上传。跨度>
标签: ruby-on-rails ruby reactjs file-upload carrierwave