VaporFileUploadService

Introduction

The VaporFileUploadService provides functionalities to upload a file to a backend which uses Laravel Vapor.
Instead of traditionally sending the file to a backend API this service will send the file straight to an Amazon S3 bucket.

Data flow

The data flow of the VaporFileUpload service is a little different than the traditional way of uploading files.
The flow is as following:

  1. First a request is sent to the endpoint /vapor/signed-storage-url. This is done to retrieve the url and uuid of a temporary S3 storage location.
    An example of the response is as followed:

    {
    bucket: "capturum-intergrip-test"  
    headers: {
    Host: ["capturum-intergrip-test.s3.eu-central-1.amazonaws.com"],
     x-amz-acl: ["private"],}  
    key: "tmp/3aa77997-4e50-416b-9f93-9d0ddd0efd4e"  
    url: "https://capturum-intergrip-test.s3.eu-central-1.amazonaws.com/tmp/3aa77997-4e50-416b-9f93-9d0ddd0efd4e?x-amz-acl=private&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Security-Token=IQoJb3JpZ2luX2VjENX%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDGV1LWNlbnRyYWwtMSJIMEYCIQDYgkUQO22nRUcY%2BVMcEE3AzB%2F43ZNO9EPo3TUb90NPEAIhANCtud6fNk5ulSb%2FDROd%2Fyr17oA7FRw9lbt2zTkA0QN2KtwBCO7%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEQARoMNDIyODYwMTgxNzgxIgzYIF8YsxXz0MXmdfcqsAFKbSev04Ye2wATpAU8xH8fHCYttIwzyiW6%2BskOQWaOEpG0WoTeNnJz40RgdvX28IZ1Dz84Jdta%2BAAso4uv%2BvtKVDWaRq7O4vGBWXGAiLHuAM0bUUMmIB5AgkKB64Kp4CI1WY2OLAo6ErtL2n4rhqXJ0gnsoeYP0%2B5sVYjmLUxVctL1%2B9oihosVdmSEpIYUZ2fMh%2BYdzsN8gSw1wa4bgGvZdnl32CxFOYBH5%2FlGuvVIWTCqyoiCBjrfARFcM49GUFDiv4xn3LSJ0UaYtHepSpBs0%2B%2BxF%2BNq1QOW%2FAosHjydoU90oH4f3ztObKbButF6na5KZ15oIRWOBE1L1sVhaJXjA7aP91uyJH71XvHLWJ634wNX16NZkS%2BDfTZdToS%2BHyBXCcFuSbkMAUoP8HtdiTPHB7G%2BSgp2hUJuvmVPSQJE2MCzM2ewzOIHmXXBh8k7PR4kQkTJoreTQadRweEMOragfkSZSWwbWFsgh8NY1yDGZPx4%2BaE0%2FV48VhfcfTRaXA%2F1VqDZdoTbrRy9LQ2bd0KifCu09WcABiE%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAWE5DOKEKTO6NOS6G%2F20210305%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20210305T123434Z&X-Amz-SignedHeaders=host%3Bx-amz-acl&X-Amz-Expires=300&X-Amz-Signature=b4b839ecb9691bea20a32e99cea2722cfb1fef41c7d5e2f84b3c55c56e51e331"  
    uuid: "3aa77997-4e50-416b-9f93-9d0ddd0efd4e"
    }

    There are two important properties here: url and uuid. The url is used to upload the file to and the uuid is a reference to the allocated temporary storage location to which the file will be uploaded to.

  2. Next it takes the url which was returned by the request in step 1 and we upload the file to this url.
  3. The last step is to let the backend know where the file was stored. This is what the uuid is used for which was returned in step 2. This has to be done in the project itself and is not something which is provided by @capturum/api.

Usage

To use the VaporFileUploadService you have to first inject it into your constructor.

import { VaporFileUploadService } from '@capturum/api';

constructor(private vaporFileUploadService: VaporFileUploadService) {}

Next up use the uploadFile function of the VaporFileUploadService to upload your file:

public upload(file: File): {
    this.vaporFileUploadService.uploadFile(file).subscribe(() => {
    // Do something with the response
    });
}

The uploadFiles function will return on Observable of type VaporUploadResponse. This interface looks as followed:

interface VaporFileUploadResponse {  
  type: HttpEventType,  
  data: ({ progress: number } | { uuid: string } | HttpEvent<Object>),  
}

The function will emit values for the upload progress and for the response. The type will define what kind of value is emitted. This way you can show a uploader progressbar based on the progress like so:

    this.vaporFileUploadService.uploadFile(file).subscribe((response) => {
        if (response.type === HttpEventType.UploadProgress) {
            console.log(response.data); // { progress: 10 } 
        } else {
            console.log(response.data); // { uuid: 'xxxxx-xxxxxx-xxxxxx-xxxx' } 
        }
    });

If you’re only interested in the result then you could use the filter operator to only get the response type:

this.vaporFileUploadService.uploadFile(file).pipe(
    filter((response) => response.type === HttpEventType.Response),
).subscribe((response) => {
    console.log(response.data); // { uuid: 'xxxxx-xxxxxx-xxxxxx-xxxx' }
});

Uploading multiple files

Currently the VaporFileUploadService does not support uploading multiple files. If you need to upload multiple files then you’ll have to use a forkJoin or combineLatest to send multiple requests:

    forkJoin([
        this.vaporFileUploadService.uploadFile(file),
        this.vaporFileUploadService.uploadFile(file2)
    ]).subscribe(...)