firebase / firebase-admin-node

Firebase Admin Node.js SDK
https://firebase.google.com/docs/admin/setup
Apache License 2.0
1.62k stars 370 forks source link

Unable to Upload Files Larger than 2GB to Firebase Storage #2608

Open kevinrss01 opened 3 months ago

kevinrss01 commented 3 months ago

[REQUIRED] Step 2: Describe your environment

Operating System

Browser Version

Firebase SDK Version

Firebase SDK Product:

NPM and NODE: I'm using nestJS (@10.3.9), nodeJS (v20.11.1) and npm 10.2.4

[REQUIRED] Step 3: Describe the problem

I am experiencing an issue where attempting to upload files larger than 2GB to Firebase Storage results in a GaxiosError: request to https://storage.googleapis.com/upload/storage/v1/b/[...] failed, reason: write EPROTO.

However, smaller files (e.g., 1.8GB) upload without any issues.

Steps to reproduce:

  1. Attempt to upload a file larger than 2GB using the Firebase Storage SDK in a Node.js application.
  2. Encounter the following error:
    Failed to upload file. GaxiosError: request to [https://storage.googleapis.com/upload/storage/v1/b/...] failed, reason: write EPROTO
    at Gaxios._request (/path/to/project/node_modules/gaxios/src/gaxios.ts:157:13)
    type: 'system',
    errno: 'EPROTO',
    code: 'EPROTO'

Relevant Code:

Here is a sample of the TypeScript function used for uploading:

import { Stream } from 'stream';
import { getStorageAdmin } from 'path-to-your-storage-admin-utils';

async uploadFileViaStream(fileStream: Stream, path: string): Promise<string> {
    console.debug('Uploading file to storage using stream...');
    const storage = getStorageAdmin();
    const bucket = storage.bucket('voicecheap-c1f14.appspot.com');
    const fileRef = bucket.file(path);
    const contentType =
      path.split('.').pop() === 'mp3' ? 'audio/mpeg' : 'video/mp4';

    // Verify if the file already exists
    const [exists] = await fileRef.exists();
    if (exists) {
      console.debug('File already exists. Skipping upload.');
      return fileRef.publicUrl();
    }

    return new Promise((resolve, reject) => {
      fileStream
        .pipe(
          fileRef.createWriteStream({
            contentType: contentType,
            public: true,
            metadata: {
              contentType: contentType,
              mimeType: contentType,
              type: contentType,
            },
          }),
        )
        .on('error', (error) => {
          console.error('Failed to upload file.', error);
          reject(error);
          throw new InternalServerErrorException('Failed to upload file.');
        })
        .on('finish', async () => {
          // Make the file publicly accessible
          try {
            await fileRef.makePublic();
            console.debug('File uploaded and made public.');
            resolve(fileRef.publicUrl());
          } catch (error) {
            console.error('Failed to make the file public.', error);
            reject(error);
            throw new InternalServerErrorException(
              'Failed to make the file public.',
            );
          }
        });
    });
  }
google-oss-bot commented 3 months ago

I found a few problems with this issue:

aendel commented 3 weeks ago

+1