Skip to content
guillemc23 edited this page Apr 21, 2023 · 8 revisions

As of version 2.0, Evaporate supports the Promise interface. Instead of instantiating the Evaporate class as you would in earlier verions, use the create class method of Evaporate like so:

Evaporate.create(config)
    .then(
        function (evaporate) {
            evaporate.add(add_config)
                .then(
                    function (awsKey) { console.log('Successfully uploaded:', awsKey); },
                    function (reason) { console.log('Failed to upload:', reason); }
                )
        },
        function (reason) {
            console.log('Evaporate failed to initialize:', reason);
        });

The promise create returns will resolve with a reference to the fully initialized evaporate instance or reject with a reason as to why Evaporate could not initialize. If you use timeUrl, you should use the create method because the promise only resolves after the time offset is available.

config minimally consists of bucket and aws_key and one of the following combinations of signing options:

  1. A custom signerUrl that returns the signature or signing response required for the specified awsSignatureVersion.
  2. A custom authorization method defined with customAuthMethod.

signerUrl is not invoked if using a customAuthMethod. signResponseHandler can also be provided for additional processing of responses from signerUrl. If the request to signerUrl responds with 401 Unauthorized or 403 Permission Denied, then the upload will stop. Any other status will attempt to retry the request.

If the custom authorization Promise rejects, then the upload will stop.

Available configuration options:

  • bucket: the name of your bucket to which you want the files uploaded, for example 'my.bucket.name'. Note that the cloudfront option will determine where the bucket name appears in the aws_url.

  • aws_key: default=undefined, your AWS key, for example 'AKIAIQC7JOOdsfsdf'. Required when awsSignatureVersion is '4'.

  • signerUrl: a url on your application server which will sign the request according to your chosen AWS signature method (Version 2 or 4). For example 'http://myserver.com/auth_upload'. When using AWS Signature Version 4, this URL must respond with the V4 signing key. If you don't want to use a signerURL and want to sign the request yourself, then you sign the request using signResponseHandler.

  • sendCanonicalRequestToSignerUrl: default=false, whether to send the AWS Signature V4 canonical request as a pameter to signerUrl. If enabled, the canonical request will be present in the request as canonical_request.

  • customAuthMethod: a method that returns an implementation of Promises/A+. The promise resolves with the AWS object key of the uploaded object. The method is passed the signParams, signHeaders, calculated string to sign and the datetime used in the string to sign.

    For example:

    function (signParams, signHeaders, stringToSign, signatureDateTime, canonicalRequest) { // pluggable signing
        return new Promise(function (resolve, reject) {
            resolve('computed signature');
        })
    }

    Use a customAuthMethod if you want to use AWS Lambda for signature calculation. If the Promise rejects, then the file upload will stop.

  • computeContentMd5: default=false, whether to compute and send an MD5 digest for each part for verification by AWS S3. This option defaults to false for backward compatibility; however, new applications of Evaporate should always enable this to assure that uploaded files are exact copies of the source (copy fidelity).

  • signResponseHandler: default=null, a method that handles the XHR response with the signature. It must return the encoded signature. If you set this option, Evaporate will pass it the response it received from the signerUrl. The method must return a Promise that resolves with the signature or rejects with a reason. For example:

    function (response, stringToSign, signatureDateTime) {
        return new Promise(function (resolve, reject) {
            resolve('computed signature');
        }
    }
  • logging: default=true, whether Evaporate outputs to the console.log - should be true or false

  • maxConcurrentParts: default=5, how many concurrent file PUTs will be attempted

  • partSize: default = 6 * 1024 * 1024 bytes, the size of the parts into which the file is broken

  • retryBackoffPower: default=2, how aggressively to back-off on the delay between retries of a part PUT

  • maxRetryBackoffSecs: default=300, the maximum number of seconds to wait between retries

  • maxFileSize: default=no limit, the allowed maximum files size, in bytes.

  • progressIntervalMS: default=1000, the frequency (in milliseconds) at which progress events are dispatched

  • readableStreams: default=false, if the file you upload is a Node ReadableStream, set this option to true and and provide a readableStreamPartMethod.

  • readableStreamPartMethod: default:null, returns a ReadableStream implemented as an ArrayBufferView Uint8Array. For example:

    function (file, start, end) {
      // Node returns a Stream of Uint8Array
      return fs.createReadStream(file.path, {start: start, end: end});
    }
  • aws_url: default='https://s3.amazonaws.com', the S3 endpoint URL. If you have a bucket in a region other than US Standard, you will need to change this to the correct endpoint from the AWS Region list.

    How Evaporate Determines the Default AWS Url

    Evaporate will create a virtual host that includes the bucket when cloudfront is set when it creates the default AWS url. Evaporate always creates a virtual host with S3 transfer acceleration enabled.

    1. With s3Acceleration: https://<bucket>.s3-accelerate.amazonaws.com.
    2. When awsRegion is 'us-east-1': https://s3.amazonaws.com.
    3. Otherwise, for any other value like 'eu-central-1': https://s3-eu-central-1.amazonaws.com.

    To use a dualstack endpoint for the 'us-east-1' region, specify aws_url like so: https://s3.dualstack.us-east-1.amazonaws.com.

    Note: If you specify your own aws_url as an S3 virtual host, then you must also explicitly set cloudfront.

  • awsRegion: default='us-east-1', Required when awsSignatureVersion is '4'. When set, the awsRegion will help determine the default aws_url to use. See notes above for aws_url.

  • awsSignatureVersion: default='4', Determines the AWS Signature signing process version to use. Set this option to '2' for Version 2 signatures.

  • cloudfront: default=false, When true, Evaporate creates an S3 virtual host format aws_url. For example, for awsRegion 'us-east-1', the bucket appears in the path https://s3.amazonaws.com/<bucket> by default but with cloudfront set, as part of the host: https://<bucket>.s3.amazonaws.com.

  • s3Acceleration: default=false, whether to use S3 Transfer Acceleration.

  • xhrWithCredentials: default=false, set the XMLHttpRequest xhr object to use credentials.

  • timeUrl: default=undefined, a url on your application server which will return a DateTime. for example '/sign_auth/time' and return a RF 2616 Date (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html) e.g. "Tue, 01 Jan 2013 04:39:43 GMT". See https://github.com/TTLabs/EvaporateJS/issues/74.

  • cryptoMd5Method: default=undefined, a method that computes the MD5 digest according to https://www.ietf.org/rfc/rfc1864.txt. Only applicable when computeContentMd5 is set. Method signature is function (data) { return 'computed MD5 digest of data'; } where data is a JavaScript ArrayBuffer representation of the part payload to encode. If you are using:

    • Spark MD5, the method would look like this: function (data) { return btoa(SparkMD5.ArrayBuffer.hash(data, true)); }.
    • Node.js: function (data) { return crypto.createHash('md5').update(Buffer.from(data)).digest('base64'); }.
    • AWS SDK for JavaScript: function (data) { return AWS.util.crypto.md5(data, 'base64'); }.
  • cryptoHexEncodedHash256: default=undefined, a method that computes the lowercase base 16 encoded SHA256 hash. Required when awsSignatureVersion is '4'.

    • Node.js: function (data) { return crypto.createHash('sha256').update(Buffer.from(data)).digest('hex'); }.
    • AWS SDK for JavaScript: function (data) { return AWS.util.crypto.sha256(data, 'hex'); }.
  • mockLocalStorage: default=false, whether to use a local object to cache Evaporate upload attempts, rather than localStorage. Set this if you want to resume uploads in non-browser environments. If set, then a plain old JavaScript object will be used instead of localStorage, even if localStorage is supported by the environment.

  • s3FileCacheHoursAgo: default=null (no cache), whether to use the S3 uploaded cache of parts and files for ease of recovering after client failure or page refresh. The value should be a whole number representing the number of hours ago to check for uploaded parts and files. The uploaded parts and file status are retrieved from S3. If no cache is set, Evaporate will not resume uploads after client or user errors. Refer to the section below for more information on this configuration option.

  • onlyRetryForSameFileName: default=false, if the same file is uploaded again, should a retry only be attempted if the file name matches the time that file name was previously uploaded. Otherwise, the upload is resumed to the previous file name that was used.

  • allowS3ExistenceOptimization: default=false, whether to verify file existence against S3 storage. Enabling this option requires that the target S3 bucket object permissions include the s3:GetObject action for the authorized user performing the upload. If enabled, if the uploader believes it is attempting to upload a file that already exists, it will perform a HEAD action on the object to verify its eTag. If this option is not set or if the cached eTag does not match the object's eTag, the file will be uploaded again. This option is only enabled if computeContentMd5 is enabled.

  • signParams: Object. an object of key/value pairs that will be passed to all calls to the signerUrl. The value can be a function. For example:

    signParams: {
    vip: true,
    username: function () { return user.name; }
    }
  • signHeaders: Object. an object of key/value pairs that will be passed as headers to all calls to the signerUrl.The value can be a function. For example:

    signHeaders: {
    xVip: 1,
    x-user-name: function () { return user.name; }
    }