Issue with Progress Bars in Uppy Plugin
I’m currently working on a custom Uppy plugin called MinioUploader
, which utilizes an underlying S3FileFieldClient
to upload files to a Minio server. The file uploads are successful; however, I’m having trouble getting the progress bars to work as expected.
I’m emitting the upload-progress
event with progress information, but the progress bars in the Uppy UI are not updating during the upload.
I’m wondering if I missed something in my implementation or if there’s a specific way to integrate progress bars in Uppy when using a custom uploader plugin. Any guidance or suggestions would be greatly appreciated.
I’ve implemented progress tracking in my Uppy plugin as follows:
// Define your custom MinioUploader plugin
export default class MinioUploader extends BasePlugin {
constructor(uppy, opts) {
super(uppy, opts);
this.id = 'minioUploader';
this.type = 'uploader';
this.title = 'Minio Uploader';
this.defaultLocale = locale
this.i18nInit();
this.uploadFile = this.uploadFile.bind(this);
// Set default options and merge with provided options
this.opts = Object.assign({
onProgress: this.onProgress.bind(this),
}, opts);
this.client = new S3FileFieldClient(this.opts);
}
// Function to upload a file
async uploadFile(fileIDs) {
const filesArr = this.uppy.getFiles(); // Access uppy object using this.uppy
for (const file of filesArr) {
try {
const fieldValue = await this.client.uploadFile(
file.data,
file.id,
'fusion_sync.FusionSync.file'
);
console.log('Uploaded:', fieldValue);
// Handle the uploaded file or fieldValue as needed
} catch (error) {
console.error('Error uploading file:', error);
// Handle the upload error
}
}
}
I've implemented progress tracking in my Uppy plugin as follows:
onProgress(file, bytesUploaded, bytesTotal) {
this.uppy.log(`[MinioUploader] ${bytesUploaded} / ${bytesTotal} bytes`);
this.uppy.emit('upload-progress', file, {
uploader: this,
bytesUploaded,
bytesTotal,
});
}
install() {
this.uppy.addUploader(this.uploadFile);
}
uninstall() {
this.uppy.removeUploader(this.uploadFile);
}
}
class S3FileFieldClient {
constructor(options) {
const { baseUrl, apiConfig = {} } = options;
this.api = axios.create(Object.assign({}, apiConfig, {
baseURL: baseUrl.replace(/\/?$/, '/')
}));
this.onProgress = options.onProgress;
}
async initializeUpload(file, fieldId) {
const response = await this.api.post('upload-initialize/', {
field_id: fieldId,
file_name: file.name,
file_size: file.size,
content_type: file.type,
});
return response.data;
}
async uploadParts(file, dataId, parts) {
const uploadedParts = [];
let fileOffset = 0;
for (const part of parts) {
const chunk = file.slice(fileOffset, fileOffset + part.size);
const response = await this.api.put(part.upload_url, chunk, {
onUploadProgress: (e) => {
// Emit Uppy's 'upload-progress' event with progress information
this.onProgress(
dataId,
e.loaded,
e.total,
);
}
});
uploadedParts.push({
part_number: part.part_number,
size: part.size,
etag: response.headers.etag
});
fileOffset += part.size;
}
return uploadedParts;
}
async completeUpload(multipartInfo, parts) {
const response = await this.api.post('upload-complete/', {
upload_signature: multipartInfo.upload_signature,
upload_id: multipartInfo.upload_id,
parts
});
const { complete_url: completeUrl, body } = response.data;
await axios.post(completeUrl, body, {
headers: { 'Content-Type': null }
});
}
async finalize(multipartInfo) {
const response = await this.api.post('finalize/', {
upload_signature: multipartInfo.upload_signature
});
return response.data.field_value;
}
async uploadFile(file, dataId, fieldId) {
try {
const multipartInfo = await this.initializeUpload(file, fieldId);
const parts = await this.uploadParts(file, dataId, multipartInfo.parts);
await this.completeUpload(multipartInfo, parts);
const value = await this.finalize(multipartInfo);
return value;
} catch (e) {
console.error('Error uploading file:', e.message);
}
}
}