OWL ‐ Uploading Files - vec-ltd/odoo-docs GitHub Wiki

Uploading Files

Whether it is an image or a pdf file, a file it remains and what follows are some of the challenges and solutions for them.

First way is the easiest way

You can have some code in your .js file of your component which will render a built-in Odoo action window. This way is the easiest as you can just select the image you wish to upload and Odoo takes care of the rest.

![image](Odoo/assets/Screenshot 2023-12-20 at 14.56.07.png)

async toQuestionFormView (question) {
    this.action.doAction({
      name: "Question Details",
      type: "ir.actions.act_window",
      res_model: "audit.snapshot_question",
      views: [[false, "form"]],
      target: "new",
      res_id: question.id,
    })
  }

Or you would like an html input tag from which to select a file - This is the much harder way.

![image](Odoo/assets/Screenshot 2023-12-20 at 14.24.38.png)

Lets cover the 2nd option

Step 1 (OWL) - The html code to upload a file

<form method="post" enctype="multipart/form-data">
  <input
     type="file"
     t-on-change="event => this.onChangeAttach(event, {...question})"
     id="image-upload"
     name="image-upload"
     accept="image/*" />
</form>

Step 2 (OWL) - The javascript code to receive the uploaded file

async onChangeAttach(event, question) {
    const pictureFile = event.target.files[0]
    const base64EncodedFile = await this.convertFileToBase64(pictureFile)
    this.state.fileToUpload = base64EncodedFile
}

Step 3 (OWL) - The javascript code to base64 encode your file

convertFileToBase64 = (file) => {
    return new Promise((resolve, reject) => {
      const fileReader = new FileReader()
      fileReader.readAsDataURL(file)

      fileReader.onload = () => {
        resolve(fileReader.result)
      }

      fileReader.onerror = (error) => {
        reject(error)
      }
    })
  }

Step 4 (OWL) - The javascript code to send your file to the Backend (Odoo)

// A simple function which calls the overwritten `write` method of the `SnapshotQuestion` class
  async saveQuestionChanges (question) {
    const new_values = {
          'comment': question['comment'],
          'answer_yn': question['answer_yn'],
          'answer_star': question['answer_star'],
          'answer_perc': question['answer_perc'],
          'image': this.state.fileToUpload,
        }

    // Structure:  'model', 'function to execute in model', 'object id to be edited', 'new values in a dictionary'
    await this.orm.call(
        'audit.snapshot_question',
        'write',
        [question.id],
        {'vals': new_values},
    )
  }

Step 5 (Odoo) - The field declared in the model

# It can be an Image field - Note that `Image` starts with a capital letter.
image = fields.Image(string="image")

# Or it can be a Binary field - Note that `Binary` starts with a capital letter.
image = fields.Binary(string="image")

Step 6 (Odoo) - The python code of the overwritten write method

    def write(self, vals):
        image_encoded = str(vals["image"])

        try:
            image_encoded = image_encoded.split(",")[1]
            vals["image"] = image_encoded
        except:
            return super(SnapshotQuestion, self).write(vals)
        return super(SnapshotQuestion, self).write(vals)

Lets understand the magic in step 6

When you uploaded a file through Odoo's built-in action.

In this case the base64 encoding is done for you and the data sent to the Backend (Odoo - Python) will be a very long string that looks something like this {'image': 'iVBORw0KGgoAAAANSUhEUgAAB18}

However, when you upload a file the hard way, you have to do the encoding first like you did in step 3 and then the data sent to the Backend (Odoo - Python) will look something like this {'image': 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB0UAAAPBCAYAAACBf}

That is why there is some magic that needs to be done before super().write()can be called. You have to get rid of the part that reads data:image/png;base64,and keep only the very long alphanumeric string.

⚠️ **GitHub.com Fallback** ⚠️