Upload Files from Vue.js to Rails with ActiveStorage

Simple enough, isn't it ? Well, no, but yes, but maybe I'll just be honest there and confess this took me way longer than I'd love to admit.

The goal of the game is to create an Item from a Vue.js user form, and store it quietly in our Ruby on Rails API, using ActiveStorage. An item will have a name, description, and of course, the user-uploaded picture ! We're going to build a Vue.js component and the Rails controller. Let's dance !

Our Vue.js Form Component

The HTML Template

    <h2>Add an item</h2>
    <form enctype="multipart/form-data">
      <p>Name: </p><input v-model="inputName">
      <p>Description :</p><textarea v-model="inputDescription"></textarea>
      <p>Picture :</p><input type="file" ref="inputFile" @change=uploadFile()>
      <button @click=createItem>Create this Item !</button>

The HTML part is simple enough. Make sure to add that enctype="multipart/form-data". Another possibility is to just add Content-Type: multipart/form-data to the header of our javascript POST request. But I prefer adding complexity to HTML instead.

Please also notice how we activate the function uploadFile() when a change is detected on the file upload button.

The Javascript

export default {
  name: 'itemsForm',
  // Here is the data we get from our HTML Form.
  data () {
    return {
      inputName: "",
      inputDescription: "",
      inputPicture: null
  methods: {
    // Saving the file in our data to send it !
    uploadFile: function() {
      this.inputPicture = this.$refs.inputFile.files[0];

    // Collecting everything inside our FormData object
    createItem: function() {
      const params = {
        'name': this.inputName,
        'description': this.inputDescription,
        'picture': this.inputPicture

      let formData = new FormData()

        ([key, value]) => formData.append(key, value)
      // Finally, sending the POST request with our beloved Axios
      axios.post('/item', formData)

No black magic there, everything is simple. We iterate over the params to add them to a FormData object, then we send it.

Our Rails Controller

class ItemsController < ApplicationController
  def create
    item = Item.create item_params
    # Attach picture to our item, if available
    attach_main_pic(item) if admin_params[:picture].present?

    # Reply with success if the object was saved, or failure if it was not.
    if item.persisted?
      render json: item, status: 200
      render json: item, status: 400


  def attach_main_pic(item)

  def item_params
      name: admin_params[:name],
      description: admin_params[:description],

  def admin_params

Don't forget to add post 'items' => 'items#create' to your Rails routes. You might also need to deactivate the parameter wrapping in the initializers.

What else to do ?

I kept the code simple there, but obviously you should add validations in the controller, both on size and file types. You don't want just any crap taking all your precious server space !

If you want multiple file upload, Check out this link !open in new window

Last Updated:
Contributors: Samuelfaure