I am trying to upload and send a simple image file to my Rails 7 API using FormData from React as I read it is only right to use that while uploading a file.
this is what my code looks like
const handleSubmit = (e) => {
e.preventDefault();
let formData = new FormData(e.currentTarget);
const data = Object.fromEntries(formData)
dispatch(createAsset(data)); //this a redux function
e.currentTarget.reset()
};
<form onSubmit={handleSubmit} className={toggleForm && 'hide-form'}>
<div>
<label>Property Title</label>
<input type="text" id="name" name="name" />
</div>
<div>
<labal>image upload</labal>
<input type="file" name="image" />
</div>
<button className="btn" type="submit"> create assets</button>
</form>
HTTP request is made
the other field hit the rails console with values except the image_field which shows an empty object in the rails console (when I try to debug I see an image object in the React debugging). I would love to know if I’m doing something wrong and why the image_field sends an empty image object to my Rails app.
const createAsset = createAsyncThunk('asset/create_asset', async (data) => {
const response = await fetch(`${baseUrl}assets`, {
method: 'POST',
headers: {
'Content-type': 'application/json',
Authorization: `Bearer ${token()}`,
},
body: JSON.stringify(data),
}).then((res) => res.json());
return response;
});
this is the rails controller action
def create
@asset = Asset.new(asset_params)
if @asset.save
render json: @asset, status: :created
else
render json: @asset.errors, status: :unprocessable_entity
end
end
def asset_params
params.require(:asset).permit(:name, :image)
end
asset modal
class Asset < ApplicationRecord
has_one_attached :image
def image_url
# Rails.application.routes.url_helpers.rails_blob_path(image, only_path: true)
Rails.application.routes.url_helpers.url_for(image) if image.attached?
end
end
PS: I did not detail the rails setup as I strongly believe the issue is from the React code
2
Answers
The problem in your React code is this header:
You’re transmitting the data in JSON format, which is the incorrect format when handling file uploads. What you should be using is this encoding type:
You can set this in your
fetch
config, BUT the recommended way to do it is to declare it in the form element via the enctype attribute:To quote from the MDN docs:
Here’s your updated fetch logic:
What if
multipart/form-data
ascontent-type
for your request?FormData
?Reference: