VueJS download file from server


Next interesting thing for my Evendy.ru app - feature request to generate and import events directly to the *.ics files.

Good starting point for this type of feature - nice iCalendar gem.

Let’s add a simple link to our Event page:

<a v-on:click="get_cal()" class="btn btn-link btn-danger">
  Календарь
</a>

ev

Great, next let’s write our get_cal method and will add it to the methods section:

    get_cal: function () {
      this.$http.post(this.$route.path + '/calendar', {}, {responseType: 'blob'})
        .then((response) => {
          let blob = new Blob([response.data], { type: 'text/calendar' })
          let link = document.createElement('a')
          link.href = window.URL.createObjectURL(blob)
          link.download = 'event.ics'
          link.click()
        })
        .catch((err) => {
          console.log(err)
        })
    },

According this example, we should prepare raw blob data on server side, and send it to the our frontend application in the response param.

But to simulate download, we need to create some temporary link object, with href which points to the our raw blob.

let blob = new Blob([response.data], { type: 'text/calendar' })
let link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)

Great, in the next step, let’s check our server side. Our CalendarCommand:

class Features::CalendarCommand < BaseCommand
  step :generate

  def generate(id:)
    event = Event.find_by(id: id)

    cal = Icalendar::Calendar.new
    cal_event = Icalendar::Event.new
    
    cal_event.dtstart = Icalendar::Values::DateTime.new(event.start_at)
    cal_event.dtend = Icalendar::Values::DateTime.new(event.end_at)
    cal_event.summary = event.title
    cal_event.location = event.address
    cal_event.uid = cal_event.url = "http://evendy.ru/events/#{event.to_param}"
    
    if cal.add_event(cal_event)
      cal.publish
      Right(cal)
    else
      Left(error(I18n.t('errors.base')))
    end
  end
end

Here, we created FeaturesController and reloaded our run_command method with new calendar_response method:

def calendar_response(data)
  send_data data.to_ical
end

And controller:

class FeaturesController < BaseController
  def calendar
    cal = run_command(Features::CalendarCommand, {id: params[:id]})
    headers['Content-Type'] = 'text/calendar; charset=UTF-8'
  end

  private

  def run_command(command, params)
    command.run(params) do |m|
      m.success {|object| calendar_response(object) }
      m.failure {|errors| error_response(errors) }
    end
  end
end

That’s it. Let’s download generated file and add our event.

cev