Upload image using Axios/Vue.js (AdonisJS REST)


#1

With Vue.js, following a button click, I want to upload an image to my REST API:

async submit() {
  console.log(this.photo) // this is fine
  let data = new FormData()
  data.append('file', this.photo)
  let url = 'http://127.0.0.1:3333/upload'
  let options = {
    headers: {
      'content-type': 'multipart/form-data'
    }
  }
  await this.$axios.$post(url, data, options) 
}

Now on the server (my controller’s corresponding function), I run this:

async upload( {request, response} ) {                                                                                             
  console.log(request.all())    
}

And the output is:

{}

As you can see, the image is not uploaded; why?
Thank you for any highlights,
Billal BEGUERADJ


#2

You should read the docs for file uploads: https://adonisjs.com/docs/4.1/file-uploads


#3

Hi @kayyyy thank you for the feedback. I read the page you linked to and I tested the code described there successfully. However I am trying to implement the same using Axios in my Nuxt.js client application. My server is a RESTful AdonisJS application. For the moment, I can not overcome the step described in my question.


#4

If you’re using Nuxt.js you should ask in a Nuxt.js group or something like that, because this seems not a related issue with Adonisjs.

First, I would check if you’re able to send some data with axios.

          this.$axios
            $post(`/upload`,{
                foo: 'bar' 
            })
            .then(response => {
                consol.log(response);
            })

or anything like that. Try to debug, log the response in Adonis etc.


#5

My code above transfers all data to server as long as is it not an image.
It also transfers the image’s attributes separately, I mean this works:

data.append('file', this.photo.name) // this.photo.size ...etc

But the whole file does not: data.append('file', this.photo.name)
Personally I tend to believe this is AdonisJS issue


#6

@virk
Could you please tell me what I am missing in this scenario?

I tested my Nuxt.js client code as it is (without modifications) with a different RESTful API that I set using Flask (a Python framework), and this server clearly processes the request successfully.

Below is a screenshot, you can see on my Ubuntu Terminal the output of the my image’s name (test.jpg) along with a message indicating the upload is successful:


#7

Hey @begueradj! :wave:

Could you please update your code to see how it is right now?
It should be request.file() and not request.all() as state in the documentation.


#8

@romain.lanz Thank you for trying to help.
I just fixed the issue after more debugging and a little modification of my axios request (and yes, I had to use request.file() as you suggesed -which thing I used numerous times previously but did not work).
I am now able to get my file on the AdonisJS REST API server.
I will write an article about this on my blog to share the information.
Note that I reproduced the file upload process as described in the documentation, but I want to use axios (within Nuxt.js) for my particular situation.
Thank you very much.


#9

Glad you fixed it!

Maybe you could share here the solution you used and mark it as the solution so other people could learn from you. :+1:


#10

You are right, it is maybe even better to share the solution here, so here is how I run the client request:

async submit() {
  let formData = new FormData()
  formData.append('file',  this.photo)
  let url = 'http://127.0.0.1:3333/upload'
  let config = {
    headers: {
      'content-type': 'multipart/form-data'
    }
  }
  await this.$axios({
   	method: 'post',
   	url: url,
   	data:  formData,
   	config: config
  })      

We can code the await statement in one line as I did previously thought: await this.$axios.$post(url, formData, config)
And in the controller, I used request.file('file') as @romain.lanz suggested:

'use strict'

const Helpers = use('Helpers')

class PhotoController {
  async upload( {request, response} ) {
    const photo = request.file('file')
    await photo.move(Helpers.tmpPath('photos'), {
      name: new Date().getTime() +'.'+avatar.subtype,
      overwrite: true
    })
  }
}

module.exports = PhotoController

Do not make a typo like I did: you must use the same key name to access the file both on the client: formData.append('keyNameGoesHere', this.photo) and on the server: const photo = request.file('keyNameGoesHere')
Hope this will help someone in the future.