I’m working on implementing the Background Fetch API in my Vue project to enable file uploads to an S3 bucket. The goal is to allow the upload process to continue even if the user closes the screen, which is particularly useful for a mobile web application. This functionality ensures that file uploads are completed successfully in the background, providing a seamless user experience without interruption.
This is my sample code:
In service-worker.js:
self.addEventListener("install", (event) => {
event.waitUntil(console.log("Service worker installing"));
});
self.addEventListener("activate", (event) => {
console.log("Service Worker activating.");
});
self.addEventListener("fetch", (event) => {
console.log("This is fetch");
});
self.addEventListener("backgroundfetchsuccess", async (event) => {
const bgFetch = event.registration;
const records = await bgFetch.matchAll();
for (const record of records) {
const response = await record.responseReady;
if (!response.ok) {
throw new Error(`Error response status: ${response.status}`);
}
console.log(`File uploaded successfully: ${response.status}`);
}
console.log("Background fetch success:", event);
});
self.addEventListener("backgroundfetchfail", async (event) => {
console.log("Background fetch fail:", event);
});
self.addEventListener("backgroundfetchabort", async (event) => {
console.log("Background fetch abort:", event);
});
And this is my upload function:
const uploadFile = async () => {
if (!selectedFile.value) {
message.value = "No file selected";
return;
}
message.value = "Generating presigned URL...";
let presignedUrl;
try {
const s3Client = new S3Client({
region: s3Config.region,
credentials: {
accessKeyId: s3Config.accessKeyId,
secretAccessKey: s3Config.secretAccessKey,
},
});
const command = new PutObjectCommand({
Bucket: s3Config.bucketName,
Key: selectedFile.value.name,
ContentType: selectedFile.value.type,
});
presignedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600 });
} catch (error) {
message.value = `Error generating presigned URL: ${error.message}`;
return;
}
message.value = "Uploading...";
if ("BackgroundFetchManager" in self) {
try {
const swReg = await navigator.serviceWorker.ready;
console.log("Service Worker ready:", swReg);
const bgFetch = await swReg.backgroundFetch.fetch(
"upload-file-abc",
[
new Request(presignedUrl, {
method: "PUT",
body: selectedFile.value,
headers: { "Content-Type": selectedFile.value.type },
}),
],
{
title: "File Upload",
downloadTotal: selectedFile.value.size,
}
);
bgFetch.addEventListener("progress", (event) => {
if (!event.uploadTotal || !event.uploaded) return;
const percent = Math.round((event.uploaded / event.uploadTotal) * 100);
console.log(`Upload progress: ${percent}%`);
});
} catch (error) {
message.value = `Error uploading file: ${error.message}`;
}
} else {
message.value = "Background Fetch API not supported";
}
};
When I try to upload the file it triggers: Background fetch fail event
Am I missing something..?