Skip to content

File stored in blob storage can't be reached #470

@mhauken

Description

@mhauken

I'm able to upload png to blob storage (or at least it seems like that 🙈), but when trying to access it I only get:
This site can't be reached.

Currently on: Next 14.0.0 - App Router Route Handlers

I'm rendering a canvas-image to a png. This is the function where I'm sending it to blob-storage

page.tsx:

// Convert the canvas to a Blob object
      canvas.toBlob(async (blob) => {
        if (!blob) {
          throw new Error('Failed to convert canvas to Blob');
        }

        console.log(blob);

        // Send a POST request to the upload endpoint
        const response = await fetch(
          '/api/poster/upload?filename=filename.png',
          {
            method: 'POST',
            body: blob,
          },
        );

        // Parse the response as JSON
        const result = (await response.json()) as PutBlobResult;

        // Store the image URL in the component's state
        setImageUrl(result.url);

        // Log the result
        console.log(result);
        setIsLoading(false); // End loading
      }, 'image/png');

In api/poster/upload/route.ts

import { put } from '@vercel/blob';
import { NextResponse } from 'next/server';

export async function POST(request: Request): Promise<NextResponse> {
  const { searchParams } = new URL(request.url);
  const filename = searchParams.get('filename');

  // Read the request body stream into a Buffer
  const chunks = [];
  if (request.body) {
    let reader = request.body.getReader();
    let result = await reader.read();
    while (!result.done) {
      chunks.push(result.value);
      result = await reader.read();
    }
  }
  const body = Buffer.concat(chunks);

  if (!filename || !request.body) {
    return NextResponse.json(
      {},
      { status: 404, statusText: 'Missing filename or request body' },
    );
  }

  const blob = await put(filename, body, {
    access: 'public',
  });

  return NextResponse.json(blob);
}

Everything seems to be working as espected, but when I click the link I get "This site can't be reached."
CleanShot 2023-11-05 at 11 37 29@2x

When I copy the link into the blob dashboard I get this:
CleanShot 2023-11-05 at 11 38 22@2x

Clicking download gives me the same error. The filesize is however exactly the same as when I rewrite the function to download the png instead (to make sure the png is a real png):

Code example for verifying the png works
canvas.toBlob((blob) => {
if (!blob) {
  throw new Error('Failed to convert canvas to Blob');
}
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'filename.png';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}, 'image/png');

Running the function then downloads the file in working condition locally.

Previously my route.ts looked like this:

import { put } from '@vercel/blob';
import { NextResponse } from 'next/server';

export async function POST(request: Request): Promise<NextResponse> {
  const { searchParams } = new URL(request.url);
  const filename = searchParams.get('filename');
  console.log(request.body);


  if (!filename || !request.body) {
    return NextResponse.json(
      {},
      { status: 404, statusText: 'Missing filename or request body' },
    );
  }

  const blob = await put(filename, request.body, {
    access: 'public',
  });

  return NextResponse.json(blob);
}

but then I got this logged, and it still didn't work:
ReadableStream { locked: false, state: 'readable', supportsBYOB: false }

compared to now when use the chunks I log this instead:

<Buffer 62 6c 6f 62 3a 68 74 74 70 3a 2f 2f 6c 6f 63 61 6c 68 6f 73 74 3a 33 30 30 31 2f 38 34 65 38 62 66 37 38 2d 38 38 32 65 2d 34 62 36 33 2d 62 34 61 33 ... 13 more bytes>

I would expect to download the png when I open the url, but in all the different variants I've tried I just get "This site can't be reached.". This problem might be because of my limited understanding of blob-storage, but it seems similar to #407, where it was commented that we should open a different issue with more details if we still have issues.

I've also tried with the example code from Vercel Blob Next.js Starter like this, but the result is still the same:

import { put } from '@vercel/blob';
import { NextResponse } from 'next/server';
import { customAlphabet } from 'nanoid';

export const runtime = 'edge';

const nanoid = customAlphabet(
  '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
  7,
); // 7-character random string

export async function POST(req: Request) {
  const file = req.body || '';
  const contentType = req.headers.get('content-type') || 'text/plain';
  const filename = `${nanoid()}.${contentType.split('/')[1]}`;
  const blob = await put(filename, file, {
    contentType,
    access: 'public',
  });

  return NextResponse.json(blob);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions