Custom File Upload Implementation with Element UI

Core Implementation Strategy

The key to customizing the upload behavior is utilizing the :http-request prop, which overrrides the default upload mechanism:

<el-upload
  :http-request="handleCustomUpload"
  :auto-upload="false"
  multiple
  accept=".jpg,.png,.gif"
>
  <el-button type="primary">Select Images</el-button>
  <el-button type="success" @click="triggerUpload">Upload Selected</el-button>
</el-upload>

FormData Preparation

With in your custom upload handler, prepare the FormData object with the selected file:

handleCustomUpload(uploadParams) {
  const payload = new FormData();
  const selectedFile = uploadParams.file;
  
  payload.append("imageData", selectedFile);
  
  this.executeUploadRequest(payload);
}

Complete Implementation Example

<template>
  <div class="upload-container">
    <el-upload
      ref="imageUploader"
      class="custom-uploader"
      action="#"
      :auto-upload="false"
      :multiple="true"
      :before-upload="validateFile"
      :http-request="processUpload"
      :on-error="handleUploadFailure"
      :on-success="handleUploadSuccess"
      accept="image/*"
    >
      <el-button slot="trigger" type="primary">Choose Images</el-button>
      <el-button 
        class="upload-button" 
        type="success" 
        @click="initiateUpload"
      >
        Start Upload
      </el-button>
      <div slot="tip" class="upload-tip">
        Supports JPG, PNG, GIF formats. Maximum size per file: 5MB
      </div>
    </el-upload>
  </div>
</template>

<script>
import apiService from '@/services/api';

export default {
  name: 'ImageUploadComponent',
  data() {
    return {
      uploadEndpoint: '/api/images/upload'
    };
  },
  
  computed: {
    currentUser() {
      return JSON.parse(localStorage.getItem('userData'));
    }
  },
  
  methods: {
    async processUpload(uploadObject) {
      try {
        const formData = new FormData();
        const file = uploadObject.file;
        
        formData.append('file', file);
        formData.append('userId', this.currentUser.id);
        
        const response = await apiService.post(this.uploadEndpoint, formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
            'Authorization': `Bearer ${this.currentUser.token}`
          },
          onUploadProgress: progressEvent => {
            const percentCompleted = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );
            this.updateProgress(percentCompleted);
          }
        });
        
        this.showSuccessNotification('Image uploaded successfully');
        return response.data;
        
      } catch (error) {
        this.handleError(error);
        throw error;
      }
    },
    
    validateFile(file) {
      const validFormats = ['image/jpeg', 'image/png', 'image/gif'];
      const isValidFormat = validFormats.includes(file.type);
      const isValidSize = file.size / 1024 / 1024 < 5;
      
      if (!isValidFormat) {
        this.$message.error('Invalid file format. Please select JPG, PNG, or GIF.');
        return false;
      }
      
      if (!isValidSize) {
        this.$message.error('File size exceeds 5MB limit.');
        return false;
      }
      
      return true;
    },
    
    handleUploadSuccess(response, file, fileList) {
      console.log('Upload completed:', response);
      this.$message({
        message: 'File uploaded successfully',
        type: 'success',
        duration: 3000
      });
    },
    
    handleUploadFailure(error, file, fileList) {
      const errorMessage = error.response?.data?.message || 'Upload failed';
      this.$message.error(errorMessage);
    },
    
    initiateUpload() {
      this.$refs.imageUploader.submit();
    },
    
    updateProgress(percentage) {
      // Implement progress bar update logic
    },
    
    showSuccessNotification(message) {
      this.$notify({
        title: 'Success',
        message,
        type: 'success',
        position: 'top-right'
      });
    },
    
    handleError(error) {
      if (error.response?.status === 401) {
        this.$message.warning('Session expired. Please login again.');
        this.$router.push('/login');
      } else {
        this.$message.error(error.response?.data?.message || 'Upload failed');
      }
    }
  }
};
</script>

<style scoped>
.upload-container {
  padding: 20px;
  max-width: 600px;
  margin: 0 auto;
}

.custom-uploader {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.upload-button {
  margin-left: 10px;
}

.upload-tip {
  font-size: 12px;
  color: #606266;
  margin-top: 7px;
}
</style>

Tags: element-ui file-upload Vue.js FormData axios

Posted on Thu, 10 Sep 2026 16:46:08 +0000 by jannoy