demarches-normaliennes/app/javascript/shared/activestorage/uploader.js

100 lines
2.6 KiB
JavaScript
Raw Normal View History

import { DirectUpload } from '@rails/activestorage';
import { ajax } from '@utils';
2019-02-13 14:16:22 +01:00
import ProgressBar from './progress-bar';
import FileUploadError, {
errorFromDirectUploadMessage,
ERROR_CODE_ATTACH
} from './file-upload-error';
2019-02-13 14:16:22 +01:00
/**
Uploader class is a delegate for DirectUpload instance
used to track lifecycle and progress of an upload.
2019-02-13 14:16:22 +01:00
*/
export default class Uploader {
constructor(input, file, directUploadUrl, autoAttachUrl) {
2019-02-13 14:16:22 +01:00
this.directUpload = new DirectUpload(file, directUploadUrl, this);
this.progressBar = new ProgressBar(input, this.directUpload.id, file);
this.autoAttachUrl = autoAttachUrl;
2019-02-13 14:16:22 +01:00
}
/**
Upload (and optionally attach) the file.
Returns the blob signed id on success.
Throws a FileUploadError on failure.
*/
async start() {
2019-02-13 14:16:22 +01:00
this.progressBar.start();
try {
let blobSignedId = await this._upload();
if (this.autoAttachUrl) {
await this._attach(blobSignedId);
// On response, the attachment HTML fragment will replace the progress bar.
} else {
this.progressBar.end();
this.progressBar.destroy();
}
return blobSignedId;
} catch (error) {
this.progressBar.error(error.message);
throw error;
}
}
/**
Upload the file using the DirectUpload instance, and return the blob signed_id.
Throws a FileUploadError on failure.
*/
async _upload() {
2019-02-13 14:16:22 +01:00
return new Promise((resolve, reject) => {
this.directUpload.create((errorMsg, attributes) => {
if (errorMsg) {
let error = errorFromDirectUploadMessage(errorMsg);
reject(error);
2019-02-13 14:16:22 +01:00
} else {
resolve(attributes.signed_id);
}
});
});
}
/**
Attach the file by sending a POST request to the autoAttachUrl.
Throws a FileUploadError on failure (containing the first validation
error message, if any).
*/
async _attach(blobSignedId) {
const attachmentRequest = {
url: this.autoAttachUrl,
type: 'PUT',
data: `blob_signed_id=${blobSignedId}`
};
try {
await ajax(attachmentRequest);
} catch (e) {
let message = e.response && e.response.errors && e.response.errors[0];
throw new FileUploadError(
message || 'Error attaching file.',
e.xhr.status,
ERROR_CODE_ATTACH
);
}
}
2019-02-13 14:16:22 +01:00
uploadRequestDidProgress(event) {
const progress = (event.loaded / event.total) * 100;
if (progress) {
this.progressBar.progress(progress);
}
}
directUploadWillStoreFileWithXHR(xhr) {
2020-04-30 15:42:29 +02:00
xhr.upload.addEventListener('progress', (event) =>
2019-02-13 14:16:22 +01:00
this.uploadRequestDidProgress(event)
);
}
}