File Uploads 
Learn how to upload files with Vueform.
Vueform's file upload can be configured in many ways in order to achieve different upload flows:
- Upload temporary files when the user selects them and only persist on form submit without having send over all the files again.
 - Upload files instantly and have them persist after the user selects them and issue a remove call to the backend if they choose to remove them later.
 - Upload files on form submit and have them sent along with form data.
 
Uploading Files 
By default Vueform's FileElement will issue a request to upload-temp-endpoint when the user selects a file:
<FileElement upload-temp-endpoint="/store-temp-files" />Disabling Auto-Uploading 
To disable issuing a request instantly on file select, we can set auto to false:
<FileElement
  upload-temp-endpoint="/store-temp-files"
  :auto="false"
/>In this case the user will have to press an Upload button to upload files. If files are not uploaded by the time the form is submitted, they will be force uploaded to their endpoints in separate request(s) during prepare hook, before form data is sent.
Upload Request 
The backend receives the following payload on submitting files to the endpoint:
{
  file: '(binary)', // file binary
  formKey: '...', // the form-key prop defined for `Vueform`
  path: 'file', // the full path of the file element
}Upload Response 
After storing the file temporarily on our backend, the backend has to return a JSON in the following format:
const responseBody = {
  tmp: 'y8wre123.pdf', // temp file name
  originalName: 'contract.pdf', // the original file name
}Once we receive the response from the backend the response body will be set as element value which will be sent as the file value when the form is submitted. It can be used to identify the temp file and make it persist when the form is submitted.
Skipping Temporary Upload State 
If we want to skip the temporary uploaded file state, the backend can return the final filename as a string:
const responseBody = 'final-file.pdf'Changing Upload Request Method 
By default, file upload requests are using POST method, which can be changed by providing an object for upload-temp-endpoint prop:
<FileElement :upload-temp-endpoint="{
  url: '/user/temp-files',
  method: 'PATCH',
}" />Custom Upload Handling 
We can also define an async function instead of a string endpoint for upload-temp-endpoint:
<FileElement :upload-temp-endpoint="async (value, el$) => {
  const response = await el$.$vueform.services.axios.request({
    url: 'https://my-image-server.com/api/upload-temp',
    method: 'POST',
    data: el$.form$.convertFormData({
      file: value,
    }),
    onUploadProgress: (e) => {
      el$.progress = Math.round((e.loaded * 100) / e.total)
    },
    cancelToken: el$.$vueform.services.axios.CancelToken.source().token,
  }) // errors are handled automatically
  return response.data
}" />Global Upload Endpoint Config 
When upload-temp-endpoint is not specified, its config value will be used from vueform.config.js. We can use this to set the endpoint globally:
// vueform.config.js
import { defineConfig } from '@vueform/vueform'
export default defineConfig({
  endpoints: {
    uploadTempFile: {
      url: '/vueform/file/upload-temp',
      method: 'POST',
    },
    // or
    uploadTempFile: async (value, el$) => {
      // ...
    }
  }
})Adding Params to Requests 
We can add params to our request with params when submitting to upload-temp-endpoint:
<FileElement upload-temp-endpoint="/store-temp-files" :params="{
  foo: 'bar',
}" />The backend will receive:
{
  file: '(binary)', // file binary
  formKey: '...', // the form-key prop defined for `Vueform`
  path: 'file', // the full path of the file element
  foo: 'bar', // our custom param
}Send Files on Form Submit Only 
If we don't want to have separate requests to upload files, but send them along with other form data upon submit, we can simply set upload-temp-endpoint to false:
<FileElement :upload-temp-endpoint="false" />We can also disable separate file upload requests on a config level:
// vueform.config.js
import { defineConfig } from '@vueform/vueform'
export default defineConfig({
  endpoints: {
    uploadTempFile: false
  }
})Restrict Accepted File Types 
Accepted file types can be restricted by listing extensions or MIME types separated by comma:
<!-- Extensions -->
<FileElement accept=".jpg,.png,.gif" />
<!-- MIME Types -->
<FileElement accept="image/jpeg,image/png,image/gif" />
<!-- MIME Type Groups -->
<FileElement accept="image/*,video/*" />Uploading Multiple Files 
Multiple files can be uploaded using MultifileElement:
<MultifileElement upload-temp-endpoint="/store-temp-files" />When using MultifileElement each files will be uploaded in separate requests to upload-temp-endpoint.
Sorting Files 
When uploading multiple files they can be sorted when sort: true:
<MultifileElement sort view="image" />File Validation 
We can add validation rules to files restricting its size or even dimensions when uploading images:
<FileElement :rules="[
  'min:1024', // min 1 MB file size
  'max:4096', // max 4 MB file size
  // image dimension constraints
  'dimensions:min_width=100,min_height=100,max_witdh=1000,max_height=1000,ratio=2/3',
  'dimensions:width=1024,height=768', // fixed size
]"
/>When uploading multiple files the rules concerning one file instance should be passed via file prop:
<MultifileElement
  :rules="[ // APPLIES FOR MULTIFILE ELEMENT
    'min:1', // min 1 file needs to be selected
    'max:5', // max 5 files can be selected
  ]"
  :file="{
    rules: [ // APPLIES FOR SINGLE FILES
      'min:1024', // min 1 MB file size
      'max:4096', // max 4 MB file size
      // ...
    ]
  }"
/>File Options 
We can pass other file options eg. label to single files when using MultifileElement via file prop:
<MultifileElement
  :file="{
    // ...
  }"
/>The MulfifileElement behaves as a ListElement containing FileElement instances. With file prop we can pass options to each FileElement.
Drop Area 
We can set drop: true to display a drop area instead of file upload button for both FileElement and MultifileElement:
<MultifileElement drop />Image Upload Diagram 
Here's the full diagram of the image upload process:
File Preview 
The FileElement and MultifileElement has different alternative views which can be used with view prop:
default 
<FileElement />image 
<FileElement view="image" />gallery 
<FileElement view="gallery" />Clicking Files 
The files are not clickable until they are persisted on our server (stage: 3). Once they are persisted, their URL will be composed from the file value (eg. file.pdf) prefixed with url, which is / by default.
If url is not specified for our FileElement the file will be opened in a new tab using /file.pdf URL.
If url is specified eg. https://cdn.domain.com/files/ the URL will become https://cdn.domain.com/files/file.pdf:
<!-- Click URL: https://cdn.domain.com/files/file.pdf -->
<FileElement url="https://cdn.domain.com/files/" />If the url is false the URL will be file.pdf:
<!-- Click URL: file.pdf -->
<FileElement :url="false" />If we want to turn off clickable links on files we can set clickable: false:
<!-- The file won't be clickable -->
<FileElement :clickable="false" />Here are some of the most common combinations for file click URL settings:
| Filename | url | Click path | 
|---|---|---|
file.png | - (/) | /file.png | 
file.png | false | file.png | 
file.png | /files/ | /files/file.png | 
file.png | https://cdn.com/ | https://cdn.com/file.png | 
https://cdn.com/file.png | false | https://cdn.com/file.png | 
Preview Images 
Before images are persisted on the server (stage < 3) the previews are converted to base64 and loaded to <img> tag's src attribute.
Once the files are uploaded (their value is a string, stage: 3) they will be loaded using their string value, prefixed with url or previewUrl prop.
If previewUrl is not defined then url will be used, which is also used for creating click URL.
The url prop is / by default, so if neither url or previewUrl is set and our FileElement's value is file.png it will be loaded from /file.png.
If url or previewUrl is set to eg. https://cdn.domain.com/images/ the preview will be loaded from https://cdn.domain.com/images/file.png.
If the url is false and previewUrl is not defined, the file will not have a prefix (file.png).
Here are some of the most common combinations for image preview settings:
| Filename | url (click) | previewUrl | Click path | Preview path | 
|---|---|---|---|---|
file.png | - (/) | - | /file.png | /file.png | 
file.png | false | - | file.png | file.png | 
file.png | /files/ | - | /files/file.png | /files/file.png | 
file.png | - (/) | /thumbnails/ | /file.png | /files/file.png | 
file.png | /files/ | /thumbnails/ | /files/file.png | /thumbnails/file.png | 
https://cdn.com/x.png | false | - | https://cdn.com/x.png | https://cdn.com/x.png | 
Custom File Previews 
If we need a custom file preview (eg. to render PDFs) we can create an alternative view.
Removing Files 
When files are uploaded in a temporary state, meaning their value is an object containing tmp and originalName (stage: 2) they will issue a request to remove-temp-endpoint when removed:
<FileElement remove-temp-endpoint="/remove-temp-file">When files are persisted, meaning their value is a string containing the filename (stage: 3) they will issue a request to remove-endpoint when removed.
<FileElement remove-endpoint="/remove-file">Remove requests are only issued if the file is explicitly removed by the user and not when eg. resetting, clearing or updating form data.
Remove Request 
The backend receives the following data when submitting to remove-temp-endpoint or remove-endpoint:
{
  file: '(binary)', // file binary
  formKey: '...', // the form-key prop defined for `Vueform`
  path: 'file', // the full path of the file element
}Remove Response 
The response should have a 2XX HTTP code and does not require any specific response. If the response is outside ot 2XX the remove attempt will be considered failed and the file will not change its value.
Changing Remove Request Method 
By default, file remove requests are using POST method, which can be changed by providing an object for remove-temp-endpoint or remove-endpoint props:
<FileElement
  :remove-temp-endpoint="{
    url: '/user/temp-files',
    method: 'DELETE',
  }"
  :remove-endpoint="{
    url: '/user/files',
    method: 'DELETE',
  }"
/>Custom Remove Handling 
We can also define an async function instead of a string endpoint for :remove-temp-endpoint and :remove-endpoint:
<FileElement
  :remove-temp-endpoint="async (value, el$) => {
    await el$.$vueform.services.axios.request({
      url: 'https://my-image-server.com/api/remove-temp',
      method: 'POST',
      data: el$.form$.convertFormData({
        file: value,
      }),
    }) // errors are handled automatically
  }"
  :remove-endpoint="async (value, el$) => {
    // same as above
  }"
/>Global Remove Endpoints Config 
When :remove-temp-endpoint and :remove-endpoint are not specified, their config value will be used from vueform.config.js. We can use this to set the endpoints globally:
// vueform.config.js
import { defineConfig } from '@vueform/vueform'
export default defineConfig({
  endpoints: {
    removeTempFile: {
      url: '/vueform/file/remove-temp',
      method: 'POST',
    },
    removeFile: {
      url: '/vueform/file/remove',
      method: 'POST',
    },
    // or
    removeTempFile: async (value, el$) => {
      // ...
    },
    removeFile: async (value, el$) => {
      // ...
    },
  }
})Adding Params to Requests 
We can add params to our request with params when submitting to remove-temp-endpoint or remove-endpoint:
<FileElement ... :params="{
  foo: 'bar',
}" />The backend will receive:
{
  file: '(binary)', // file binary
  formKey: '...', // the form-key prop defined for `Vueform`
  path: 'file', // the full path of the file element
  foo: 'bar', // our custom param
}Soft Remove 
If we don't want to issue separate requests when users delete files, we can set :soft-remove to true:
<FileElement soft-remove />Alternatively, we can disable remove-temp-endpoint or remove-endpoint separately by setting them to false:
<!-- Don't issue a request on removing temp file -->
<FileElement :remove-temp-endpoint="false" />
<!-- Don't issue a request on removing persisted file -->
<FileElement :remove-endpoint="false" />We can also disable separate file remove requests on a config level:
// vueform.config.js
import { defineConfig } from '@vueform/vueform'
export default defineConfig({
  endpoints: {
    removeTempFile: false,
    removeFile: false,
  }
})Loading Files 
To load files to the form, we can simply set their filenames as values for FileElement or MultifileElement:
<template>
  <Vueform ref="form$">
    <FileElement name="file" />
    <MultifileElement name="files" />
  </Vueform>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const form$ = ref(null)
onMounted(() => {
  form$.value.load({
    file: 'filename.png',
    files: [
      'file1.pdf',
      'file2.docx',
      'file3.mp3',
    ]
  })
})
</script><template>
  <Vueform ref="form$">
    <FileElement name="file" />
    <MultifileElement name="files" />
  </Vueform>
</template>
<script>
export default {
  mounted() {
    this.$refs.form$.load({
      file: 'filename.png',
      files: [
        'file1.pdf',
        'file2.docx',
        'file3.mp3',
      ]
    })
  }
}
</script>When images are loaded the previews will be composed of the loaded value for the file prefixed with url or previewUrl as we learned in Previewing Images section.
