Skip to content

fix(blob): normalize contentDisposition to use original filename when addRandomSuffix is enabled#1041

Open
matingathani wants to merge 5 commits intovercel:mainfrom
matingathani:fix/blob-client-upload-content-disposition
Open

fix(blob): normalize contentDisposition to use original filename when addRandomSuffix is enabled#1041
matingathani wants to merge 5 commits intovercel:mainfrom
matingathani:fix/blob-client-upload-content-disposition

Conversation

@matingathani
Copy link
Copy Markdown
Contributor

Summary

Fixes #903

When addRandomSuffix: true is configured for client uploads (upload()), the Vercel Blob API returns a contentDisposition header that includes the random suffix in the filename (e.g. attachment; filename="img-abc123.jpg"). Server-side put() with addRandomSuffix: true correctly returns the original filename (e.g. attachment; filename="img.jpg").

The inconsistency is in how the API handles the two request types:

  • Server put(): sends x-add-random-suffix: 1 header → API returns original filename in Content-Disposition
  • Client upload(): sends addRandomSuffix: true inside the signed client token → API returns suffixed filename in Content-Disposition

Fix: Added a normalizeContentDisposition() helper in put.ts that replaces the response filename with the original pathname filename when they differ. Applied to both the regular and multipart code paths in createPutMethod.

Changes

  • packages/blob/src/put.ts — add normalizeContentDisposition() and apply it to both regular and multipart upload responses
  • packages/blob/src/index.node.test.ts — add regression tests for the fix; update one pre-existing snapshot that used a mismatched mock (the fix now correctly derives contentDisposition from the original pathname)
  • .changeset/fix-blob-client-content-disposition.md — patch changeset

Test plan

  • pnpm test in packages/blob — all 137 tests pass
  • put('foo.txt', body, { addRandomSuffix: true }) where API returns pathname: 'foo-abc123.txt'result.contentDisposition is attachment; filename="foo.txt"
  • put('foo.txt', body, { addRandomSuffix: false })result.contentDisposition unchanged

… addRandomSuffix is enabled

When addRandomSuffix is configured for client uploads, the Blob API returns
contentDisposition with the suffixed filename. This fix ensures the SDK always
returns the original filename in contentDisposition, consistent with server put().

Fixes vercel#903
Copilot AI review requested due to automatic review settings April 2, 2026 20:11
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 2, 2026

@matingathani is attempting to deploy a commit to the Curated Tests - Permanent E2E Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 2, 2026

🦋 Changeset detected

Latest commit: bc768a4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@vercel/blob Patch
vercel-storage-integration-test-suite Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an inconsistency in the SDK’s contentDisposition value when the Blob API returns a suffixed pathname (e.g. with addRandomSuffix: true), ensuring the returned contentDisposition filename matches the original requested pathname.

Changes:

  • Add a normalizeContentDisposition() helper and apply it to both single-part and multipart put() result mapping.
  • Add regression tests for the normalization behavior and update an existing inline snapshot impacted by the normalization.
  • Add a patch changeset for @vercel/blob.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/blob/src/put.ts Normalizes contentDisposition filename to the original requested pathname (single + multipart paths).
packages/blob/src/index.node.test.ts Adds regression tests and updates an inline snapshot affected by filename normalization.
.changeset/fix-blob-client-content-disposition.md Declares a patch release and documents the behavior change.
Comments suppressed due to low confidence (1)

packages/blob/src/index.node.test.ts:487

  • The has an onUploadProgress option test now returns a snapshot where contentDisposition is normalized to progress.txt, but the mocked API response still returns pathname: "foo.txt". This makes the snapshot internally inconsistent and couples this progress test to the new normalization behavior. Consider using a dedicated mock response for this test where pathname/contentDisposition match the requested pathname (or assert pathname explicitly if the mismatch is intentional).
    it('has an onUploadProgress option', async () => {
      mockClient
        .intercept({
          path: () => true,
          method: 'PUT',
        })
        .reply(200, () => {
          return mockedFileMetaPut;
        });

      const onUploadProgress = jest.fn();

      await expect(
        put('progress.txt', 'Test Body', {
          access: 'public',
          onUploadProgress,
        }),
      ).resolves.toMatchInlineSnapshot(`
        {
          "contentDisposition": "attachment; filename="progress.txt"",
          "contentType": "text/plain",
          "downloadUrl": "https://storeId.public.blob.vercel-storage.com/foo-id.txt?download=1",
          "etag": ""abc123"",
          "pathname": "foo.txt",
          "url": "https://storeId.public.blob.vercel-storage.com/foo-id.txt",
        }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

matingathani and others added 4 commits April 2, 2026 13:15
…ails

Replaces the vague 'Failed to  retrieve the client token' message (also
fixing the double-space typo) with one that includes the HTTP status code
and status text, making auth errors (401, 403) easier to diagnose.

Closes vercel#488
@matingathani
Copy link
Copy Markdown
Contributor Author

Addressed this by adding a regression that exercises the actual multipart put() path with a suffixed completion pathname and verifies contentDisposition is normalized back to the original requested filename. I also kept the completion-path regression so both the high-level multipart flow and the shared completion behavior are covered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Blob] Client Upload Not Retaining Original Filename

2 participants