-
Notifications
You must be signed in to change notification settings - Fork 7
Description
I am implementing large file uploads with pause and resume functionality. On the frontend, I’m using React.js, and on the backend, I’m using ASP.NET Core Web API. I’ve attached both the frontend and backend code below for reference.
When I upload files to local disk storage, the pause and resume functionality works correctly. However, when I switch to Azure Blob Storage, I encounter an issue:
If I pause an upload and later resume it, the upload starts from the beginning instead of continuing from where it left off.
I want to understand:
- How can I track how much data has already been uploaded to Azure Blob Storage?
- How do I resume uploading from the correct position when the upload is paused and restarted?
If I upload a file to Azure Blob without pausing, everything works fine — the file is uploaded successfully in chunks. But pause-resume functionality breaks this flow.
Please let me know:
- What am I missing in my current implementation?
- Is my approach incorrect?
- What is the correct way to implement resumable large file uploads to Azure Blob Storage with pause and resume functionality?
Thank you for your guidance.
Reactjs code
import * as tus from "tus-js-client";
import { useState, useRef } from "react";
function App() {
const [uploadProgress, setUploadProgress] = useState(0);
const [uploading, setUploading] = useState(false);
const [paused, setPaused] = useState(false);
const uploadRef = useRef(null); // Hold the upload object across renders
const uploadTus = (e) => {
const file = e.target.files[0];
if (!file) return;
const upload = new tus.Upload(file, {
endpoint: "https://localhost:7014/files", // Replace with your TUS server
retryDelays: [0, 3000, 5000, 10000, 20000],
metadata: {
filename: file.name,
filetype: file.type,
},
onError: (error) => {
console.error("Upload failed:", error);
},
onProgress: (bytesUploaded, bytesTotal) => {
const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2);
setUploadProgress(percentage);
console.log(`${percentage}% uploaded`);
},
onSuccess: () => {
console.log("Upload completed:", upload.url);
setUploading(false);
setPaused(false);
setUploadProgress(100);
},
});
// Save reference to the upload instance
uploadRef.current = upload;
// Resume if any previous uploads exist
upload.findPreviousUploads().then((previousUploads) => {
if (previousUploads.length) {
upload.resumeFromPreviousUpload(previousUploads[0]);
}
upload.start();
setUploading(true);
setPaused(false);
});
};
const pauseUpload = () => {
if (uploadRef.current) {
uploadRef.current.abort();
setPaused(true);
setUploading(false);
console.log("Upload paused");
}
};
const resumeUpload = () => {
if (uploadRef.current) {
uploadRef.current.start();
setPaused(false);
setUploading(true);
console.log("Upload resumed");
}
};
return (
<div style={{ padding: "1rem", fontFamily: "sans-serif" }}>
<h1>TUS Upload to Azure Blob Demo</h1>
<input type="file" onChange={uploadTus} />
{uploading && <p>Uploading: {uploadProgress}%</p>}
{uploading && (
<button onClick={pauseUpload} style={{ marginRight: "10px" }}>
Pause Upload
</button>
)}
{paused && (
<button onClick={resumeUpload}>
Resume Upload
</button>
)}
</div>
);
}
export default App;
ASP.NET Core Web API code -
app.UseTus(httpContext => new DefaultTusConfiguration
{
UrlPath = "/files",
Store = new AzureBlobTusStore(
connectionString: "my-connection-string",
containerName: "my-container-name",
options: new AzureBlobTusStoreOptions
{
BlobPath = "uploads"
}
),
Events = new Events
{
OnFileCompleteAsync = async ctx =>
{
var file = await ctx.GetFileAsync();
Console.WriteLine($"Upload complete: {file.Id}");
}
}
});