Skip to content

Issue with Pause and Resume Functionality for Large File Uploads to Azure Blob Storage #15

@vaibhavagarwal01

Description

@vaibhavagarwal01

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}");
          }
      }
  });

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions