Javascript Firebase的云存储限制(组合)多个文件上载的大小

Javascript Firebase的云存储限制(组合)多个文件上载的大小,javascript,angular,firebase,google-cloud-storage,firebase-storage,Javascript,Angular,Firebase,Google Cloud Storage,Firebase Storage,在我的Angular应用程序中,我有一个带有文件上传输入的联系人表单。如果文件组合超过20 MB,则前端的文件上载输入不允许发送联系人表单在Firebase的云存储中是否有任何方法可以实现相同的逻辑?目前我只能限制20 MB,但对于每个文件,即如果有人将上载10个文件,每个19 MB s/他将无法发送表单,但这些文件将发送到我的无服务器后端,这是我不想要的 contact.component.html <mat-form-field> <!-- Accept onl

在我的Angular应用程序中,我有一个带有文件上传输入的联系人表单。如果文件组合超过20 MB,则前端的文件上载输入不允许发送联系人表单在Firebase的云存储中是否有任何方法可以实现相同的逻辑?目前我只能限制20 MB,但对于每个文件,即如果有人将上载10个文件,每个19 MB s/他将无法发送表单,但这些文件将发送到我的无服务器后端,这是我不想要的

contact.component.html

<mat-form-field>
  <!--
    Accept only files in the following format: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx. However, this is easy to bypass, Cloud Storage rules has been set up on the back-end side.
  -->
  <ngx-mat-file-input
    [accept]="[
      '.doc',
      '.docx',
      '.jpg',
      '.jpeg',
      '.pdf',
      '.png',
      '.xls',
      '.xlsx'
    ]"
    (change)="uploadFile($event)"
    formControlName="fileUploader"
    multiple
    aria-label="Here you can add additional files about your project, which can be helpeful for us."
    placeholder="Additional files"
    title="Additional files"
    type="file"
  >
  </ngx-mat-file-input>
  <mat-icon matSuffix>folder</mat-icon>
  <mat-hint
    >Accepted formats: DOC, DOCX, JPG, JPEG, PDF, PNG, XLS and XLSX,
    maximum files upload size: 20 MB.
  </mat-hint>
  <!--
    Non-null assertion operators are required to let know the compiler that this value is not empty and exists.
  -->
  <mat-error
    *ngIf="contactForm.get('fileUploader')!.hasError('maxContentSize')"
  >
    This size is too large,
    <strong
      >maximum acceptable upload size is
      {{
        contactForm.get('fileUploader')?.getError('maxContentSize')
          .maxSize | byteFormat
      }}</strong
    >
    (uploaded size:
    {{
      contactForm.get('fileUploader')?.getError('maxContentSize')
        .actualSize | byteFormat
    }}).
  </mat-error>
</mat-form-field>
contact.component.ts(文件上传器)

/**
*@description将其他文件上载到Cloud Firestore并获取文件的URL。
*@param{event}-已发送文件的对象。
*@returns{void}
*/
公共上载文件(事件:任意):无效{
//遍历所有上传的文件。
for(设i=0;i{
fileRef.getDownloadURL().subscribe((downloadURL:string)=>{
这是angularFirestore
.collection(process.env.FIRESTORE\u collection\u FILES!)//需要非空断言运算符来告知编译器此值不是空的且存在。
.add({downloadURL:downloadURL});
this.downloadURL.push(downloadURL);
});
}),
catchError((错误:任意)=>{
返回投掷器(错误);
})
)
.subscribe();
}
}
存储规则

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
        allow read; // Required in order to send this as attachment.
      // Allow write files Firebase Storage, only if:
      // 1) File is no more than 20MB
      // 2) Content type is in one of the following formats: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx.
      allow write: if request.resource.size <= 20 * 1024 * 1024
        && (request.resource.contentType.matches('application/msword')
        || request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
        || request.resource.contentType.matches('image/jpg')
        || request.resource.contentType.matches('image/jpeg')
        || request.resource.contentType.matches('application/pdf')
                || request.resource.contentType.matches('image/png')
        || request.resource.contentType.matches('application/vnd.ms-excel')
        || request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))
    }
  }
}
rules_version='2';
服务firebase.storage{
匹配/b/{bucket}/o{
匹配/{allpath=**}{
allow read;//必须将其作为附件发送。
//仅在以下情况下允许写入文件Firebase存储:
//1)文件大小不超过20MB
//2)内容类型采用以下格式之一:.doc、.docx、.jpg、.jpeg、.pdf、.png、.xls、.xlsx。

允许写入:如果Firebase安全规则在云存储中的request.resource.size限制分别适用于每个文件/对象,则它们不适用于整个操作。在云存储规则的上下文中,这种限制也没有什么意义,因为用户可以启动另一个操作来上载其他文件

应考虑的一些选择:

  • 如果您硬编码用户上载的文件的名称(这也意味着您将限制他们可以上载的文件数量),并为每个特定用户的文件创建一个文件夹,则可以确定用户文件夹中所有文件的总和,从而以这种方式限制总和

  • 或者,您可以将客户端上的所有文件压缩在一起,然后上载生成的存档。在这种情况下,安全规则可以强制执行该文件的最大大小

  • 当然,您可以包含客户端JavaScript代码来检查这两种情况下组合文件的最大大小。恶意用户可以轻松绕过此JavaScript,但大多数用户都不是恶意用户,他们会感谢您通过阻止无论如何都会被拒绝的上传来节省带宽

  • 您还可以使用HTTPS云功能作为上载目标,然后仅在文件满足您的要求时将其传递到云存储

  • 或者,您可以使用云函数,该函数在用户上传时触发,并在更改后验证该用户的文件。此时,您可以纠正这种情况


  • 其中许多场景需要(或工作得更好)您有一个可以从用户上载每个文件的路径中查看的结构。有关此结构的详细信息,请参阅上的文档。

    云存储中的Firebase安全规则限制分别适用于每个文件/对象,而不适用于整个操作。在云存储规则的上下文中,该类型的限制也将适用没有什么意义,因为用户可以启动另一个操作来上传额外的文件

    应考虑的一些选择:

  • 如果您硬编码用户上载的文件的名称(这也意味着您将限制他们可以上载的文件数量),并为每个特定用户的文件创建一个文件夹,则可以确定用户文件夹中所有文件的总和,从而以这种方式限制总和

  • 或者,您可以将客户端上的所有文件压缩在一起,然后上载生成的存档。在这种情况下,安全规则可以强制执行该文件的最大大小

  • 当然,您可以包含客户端JavaScript代码来检查这两种情况下组合文件的最大大小。恶意用户可以轻松绕过此JavaScript,但大多数用户都不是恶意用户,他们会感谢您通过阻止无论如何都会被拒绝的上传来节省带宽

  • 您还可以使用HTTPS云功能作为上载目标,然后仅在文件满足您的要求时将其传递到云存储

  • 或者,您可以使用云函数,该函数在用户上传时触发,并在更改后验证该用户的文件。此时,您可以纠正这种情况

  • 这些场景中的许多都要求(或工作得更好)您有一个
    /**
       * @description Upload additional files to Cloud Firestore and get URL to the files.
       * @param {event} - object of sent files.
       * @returns {void}
       */
      public uploadFile(event: any): void {
        // Iterate through all uploaded files.
        for (let i = 0; i < event.target.files.length; i++) {
          const randomId = Math.random()
            .toString(36)
            .substring(2); // Create random ID, so the same file names can be uploaded to Cloud Firestore.
    
          const file = event.target.files[i]; // Get each uploaded file.
    
          // Get file reference.
          const fileRef: AngularFireStorageReference = this.angularFireStorage.ref(
            randomId
          );
    
          // Create upload task.
          const task: AngularFireUploadTask = this.angularFireStorage.upload(
            randomId,
            file
          );
    
          // Upload file to Cloud Firestore.
          task
            .snapshotChanges()
            .pipe(
              finalize(() => {
                fileRef.getDownloadURL().subscribe((downloadURL: string) => {
                  this.angularFirestore
                    .collection(process.env.FIRESTORE_COLLECTION_FILES!) // Non-null assertion operator is required to let know the compiler that this value is not empty and exists.
                    .add({ downloadURL: downloadURL });
                  this.downloadURL.push(downloadURL);
                });
              }),
              catchError((error: any) => {
                return throwError(error);
              })
            )
            .subscribe();
        }
      }
    
    rules_version = '2';
    service firebase.storage {
      match /b/{bucket}/o {
        match /{allPaths=**} {
            allow read; // Required in order to send this as attachment.
          // Allow write files Firebase Storage, only if:
          // 1) File is no more than 20MB
          // 2) Content type is in one of the following formats: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx.
          allow write: if request.resource.size <= 20 * 1024 * 1024
            && (request.resource.contentType.matches('application/msword')
            || request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
            || request.resource.contentType.matches('image/jpg')
            || request.resource.contentType.matches('image/jpeg')
            || request.resource.contentType.matches('application/pdf')
                    || request.resource.contentType.matches('image/png')
            || request.resource.contentType.matches('application/vnd.ms-excel')
            || request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))
        }
      }
    }