UNPKG

@scloud/lambda-fileupload

Version:

Functions uploading/downloading files with Lambda/API Gateway where the file size is greater than the payload limit.

62 lines 9.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.tidy = tidy; exports.getUrl = getUrl; exports.putUrl = putUrl; exports.postUrl = postUrl; const s3_presigned_post_1 = require("@aws-sdk/s3-presigned-post"); const client_s3_1 = require("@aws-sdk/client-s3"); const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner"); const client = new client_s3_1.S3Client(); /** * Ensures no leading or training slashes */ function tidy(path) { return path.split('/').filter((segment) => segment).join('/'); } /** * Generates a pre-signed url for a GET request to the specified bucket and key. This is useful for downloading a file from S3 programmatically. * This allows you to download files via API Gateway & Lambda where there's a request payload size limit of 10MB & 6MB. * This is particularly useful for, say, a mobile app, as it allows the app to download a file using a url generated by its backend without needing to hold AWS credentials locally on the device. * @param expires (optional) The number of seconds until the presigned url expires, defaults to 600 (1 minute) to allow for latency plus clock drift. * @returns The signed url as a string */ async function getUrl(bucket, key, expiresIn = 600) { const command = new client_s3_1.GetObjectCommand({ Bucket: bucket, Key: tidy(key) }); return (0, s3_request_presigner_1.getSignedUrl)(client, command, { expiresIn }); } /** * Generates a pre-signed url for a PUT request to the specified bucket and key. This is useful for uploading a file to S3 programmatically. * This allows you to upload files via API Gateway & Lambda where there's a request payload size limit of 10MB & 6MB. * This is particularly useful for, say, a mobile app, as it allows the app to upload a file using a url generated by its backend without needing to hold AWS credentials locally on the device. * @param expires (optional) The number of seconds until the presigned url expires, defaults to 600 (1 minute) to allow for latency plus clock drift. * @returns The signed url as a string */ async function putUrl(bucket, key, expiresIn = 600) { const command = new client_s3_1.PutObjectCommand({ Bucket: bucket, Key: tidy(key) }); return (0, s3_request_presigner_1.getSignedUrl)(client, command, { expiresIn }); } /** * Generates pre-signed POST details suitable for use e.g. on a form on a web page to upload a file to S3. * See: https://www.npmjs.com/package/@aws-sdk/s3-presigned-post * @param bucket The bucket to upload to * @param key The key to upload to * @param expires (optional) The number of seconds until the presigned post expires, defaults to 3600 (1 hour) to give a user time to submit the form * @param maxSize (optional) The maximum size of the file to allow for upload, defaults to 100M * @returns A form action url and (hidden) field values for the upload form. For documentation see: https://www.npmjs.com/package/@aws-sdk/s3-presigned-post#user-content-post-file-using-html-form */ async function postUrl(bucket, key, expires = 3600, maxSize = 1024 * 1024 * 100) { const { url, fields } = await (0, s3_presigned_post_1.createPresignedPost)(client, { Bucket: bucket, Key: tidy(key), Expires: expires, Conditions: [ ['content-length-range', 0, maxSize], // 100M - should be plenty of headroom ], }); return { url, fields, }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlc2lnbmVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3ByZXNpZ25lZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVNBLG9CQUVDO0FBU0Qsd0JBR0M7QUFTRCx3QkFHQztBQVdELDBCQWVDO0FBN0RELGtFQUFpRTtBQUNqRSxrREFBa0Y7QUFDbEYsd0VBQTZEO0FBRTdELE1BQU0sTUFBTSxHQUFHLElBQUksb0JBQVEsRUFBRSxDQUFDO0FBRTlCOztHQUVHO0FBQ0gsU0FBZ0IsSUFBSSxDQUFDLElBQVk7SUFDL0IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSSxLQUFLLFVBQVUsTUFBTSxDQUFDLE1BQWMsRUFBRSxHQUFXLEVBQUUsWUFBb0IsR0FBRztJQUMvRSxNQUFNLE9BQU8sR0FBRyxJQUFJLDRCQUFnQixDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN6RSxPQUFPLElBQUEsbUNBQVksRUFBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztBQUN0RCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0ksS0FBSyxVQUFVLE1BQU0sQ0FBQyxNQUFjLEVBQUUsR0FBVyxFQUFFLFlBQW9CLEdBQUc7SUFDL0UsTUFBTSxPQUFPLEdBQUcsSUFBSSw0QkFBZ0IsQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekUsT0FBTyxJQUFBLG1DQUFZLEVBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7QUFDdEQsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0ksS0FBSyxVQUFVLE9BQU8sQ0FBQyxNQUFjLEVBQUUsR0FBVyxFQUFFLFVBQWtCLElBQUksRUFBRSxVQUFrQixJQUFJLEdBQUcsSUFBSSxHQUFHLEdBQUc7SUFFcEgsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsR0FBRyxNQUFNLElBQUEsdUNBQW1CLEVBQUMsTUFBTSxFQUFFO1FBQ3hELE1BQU0sRUFBRSxNQUFNO1FBQ2QsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDZCxPQUFPLEVBQUUsT0FBTztRQUNoQixVQUFVLEVBQUU7WUFDVixDQUFDLHNCQUFzQixFQUFFLENBQUMsRUFBRSxPQUFPLENBQUMsRUFBRSxzQ0FBc0M7U0FDN0U7S0FDRixDQUFDLENBQUM7SUFFSCxPQUFPO1FBQ0wsR0FBRztRQUNILE1BQU07S0FDUCxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZVByZXNpZ25lZFBvc3QgfSBmcm9tICdAYXdzLXNkay9zMy1wcmVzaWduZWQtcG9zdCc7XG5pbXBvcnQgeyBHZXRPYmplY3RDb21tYW5kLCBQdXRPYmplY3RDb21tYW5kLCBTM0NsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zMyc7XG5pbXBvcnQgeyBnZXRTaWduZWRVcmwgfSBmcm9tICdAYXdzLXNkay9zMy1yZXF1ZXN0LXByZXNpZ25lcic7XG5cbmNvbnN0IGNsaWVudCA9IG5ldyBTM0NsaWVudCgpO1xuXG4vKipcbiAqIEVuc3VyZXMgbm8gbGVhZGluZyBvciB0cmFpbmluZyBzbGFzaGVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aWR5KHBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBwYXRoLnNwbGl0KCcvJykuZmlsdGVyKChzZWdtZW50KSA9PiBzZWdtZW50KS5qb2luKCcvJyk7XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcHJlLXNpZ25lZCB1cmwgZm9yIGEgR0VUIHJlcXVlc3QgdG8gdGhlIHNwZWNpZmllZCBidWNrZXQgYW5kIGtleS4gVGhpcyBpcyB1c2VmdWwgZm9yIGRvd25sb2FkaW5nIGEgZmlsZSBmcm9tIFMzIHByb2dyYW1tYXRpY2FsbHkuXG4gKiBUaGlzIGFsbG93cyB5b3UgdG8gZG93bmxvYWQgZmlsZXMgdmlhIEFQSSBHYXRld2F5ICYgTGFtYmRhIHdoZXJlIHRoZXJlJ3MgYSByZXF1ZXN0IHBheWxvYWQgc2l6ZSBsaW1pdCBvZiAxME1CICYgNk1CLlxuICogVGhpcyBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciwgc2F5LCBhIG1vYmlsZSBhcHAsIGFzIGl0IGFsbG93cyB0aGUgYXBwIHRvIGRvd25sb2FkIGEgZmlsZSB1c2luZyBhIHVybCBnZW5lcmF0ZWQgYnkgaXRzIGJhY2tlbmQgd2l0aG91dCBuZWVkaW5nIHRvIGhvbGQgQVdTIGNyZWRlbnRpYWxzIGxvY2FsbHkgb24gdGhlIGRldmljZS5cbiAqIEBwYXJhbSBleHBpcmVzIChvcHRpb25hbCkgVGhlIG51bWJlciBvZiBzZWNvbmRzIHVudGlsIHRoZSBwcmVzaWduZWQgdXJsIGV4cGlyZXMsIGRlZmF1bHRzIHRvIDYwMCAoMSBtaW51dGUpIHRvIGFsbG93IGZvciBsYXRlbmN5IHBsdXMgY2xvY2sgZHJpZnQuXG4gKiBAcmV0dXJucyBUaGUgc2lnbmVkIHVybCBhcyBhIHN0cmluZ1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0VXJsKGJ1Y2tldDogc3RyaW5nLCBrZXk6IHN0cmluZywgZXhwaXJlc0luOiBudW1iZXIgPSA2MDApOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBjb21tYW5kID0gbmV3IEdldE9iamVjdENvbW1hbmQoeyBCdWNrZXQ6IGJ1Y2tldCwgS2V5OiB0aWR5KGtleSkgfSk7XG4gIHJldHVybiBnZXRTaWduZWRVcmwoY2xpZW50LCBjb21tYW5kLCB7IGV4cGlyZXNJbiB9KTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSBwcmUtc2lnbmVkIHVybCBmb3IgYSBQVVQgcmVxdWVzdCB0byB0aGUgc3BlY2lmaWVkIGJ1Y2tldCBhbmQga2V5LiBUaGlzIGlzIHVzZWZ1bCBmb3IgdXBsb2FkaW5nIGEgZmlsZSB0byBTMyBwcm9ncmFtbWF0aWNhbGx5LlxuICogVGhpcyBhbGxvd3MgeW91IHRvIHVwbG9hZCBmaWxlcyB2aWEgQVBJIEdhdGV3YXkgJiBMYW1iZGEgd2hlcmUgdGhlcmUncyBhIHJlcXVlc3QgcGF5bG9hZCBzaXplIGxpbWl0IG9mIDEwTUIgJiA2TUIuXG4gKiBUaGlzIGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgZm9yLCBzYXksIGEgbW9iaWxlIGFwcCwgYXMgaXQgYWxsb3dzIHRoZSBhcHAgdG8gdXBsb2FkIGEgZmlsZSB1c2luZyBhIHVybCBnZW5lcmF0ZWQgYnkgaXRzIGJhY2tlbmQgd2l0aG91dCBuZWVkaW5nIHRvIGhvbGQgQVdTIGNyZWRlbnRpYWxzIGxvY2FsbHkgb24gdGhlIGRldmljZS5cbiAqIEBwYXJhbSBleHBpcmVzIChvcHRpb25hbCkgVGhlIG51bWJlciBvZiBzZWNvbmRzIHVudGlsIHRoZSBwcmVzaWduZWQgdXJsIGV4cGlyZXMsIGRlZmF1bHRzIHRvIDYwMCAoMSBtaW51dGUpIHRvIGFsbG93IGZvciBsYXRlbmN5IHBsdXMgY2xvY2sgZHJpZnQuXG4gKiBAcmV0dXJucyBUaGUgc2lnbmVkIHVybCBhcyBhIHN0cmluZ1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHV0VXJsKGJ1Y2tldDogc3RyaW5nLCBrZXk6IHN0cmluZywgZXhwaXJlc0luOiBudW1iZXIgPSA2MDApOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBjb21tYW5kID0gbmV3IFB1dE9iamVjdENvbW1hbmQoeyBCdWNrZXQ6IGJ1Y2tldCwgS2V5OiB0aWR5KGtleSkgfSk7XG4gIHJldHVybiBnZXRTaWduZWRVcmwoY2xpZW50LCBjb21tYW5kLCB7IGV4cGlyZXNJbiB9KTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgcHJlLXNpZ25lZCBQT1NUIGRldGFpbHMgc3VpdGFibGUgZm9yIHVzZSBlLmcuIG9uIGEgZm9ybSBvbiBhIHdlYiBwYWdlIHRvIHVwbG9hZCBhIGZpbGUgdG8gUzMuXG4gKiBTZWU6IGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL0Bhd3Mtc2RrL3MzLXByZXNpZ25lZC1wb3N0XG4gKiBAcGFyYW0gYnVja2V0IFRoZSBidWNrZXQgdG8gdXBsb2FkIHRvXG4gKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gdXBsb2FkIHRvXG4gKiBAcGFyYW0gZXhwaXJlcyAob3B0aW9uYWwpIFRoZSBudW1iZXIgb2Ygc2Vjb25kcyB1bnRpbCB0aGUgcHJlc2lnbmVkIHBvc3QgZXhwaXJlcywgZGVmYXVsdHMgdG8gMzYwMCAoMSBob3VyKSB0byBnaXZlIGEgdXNlciB0aW1lIHRvIHN1Ym1pdCB0aGUgZm9ybVxuICogQHBhcmFtIG1heFNpemUgKG9wdGlvbmFsKSBUaGUgbWF4aW11bSBzaXplIG9mIHRoZSBmaWxlIHRvIGFsbG93IGZvciB1cGxvYWQsIGRlZmF1bHRzIHRvIDEwME1cbiAqIEByZXR1cm5zIEEgZm9ybSBhY3Rpb24gdXJsIGFuZCAoaGlkZGVuKSBmaWVsZCB2YWx1ZXMgZm9yIHRoZSB1cGxvYWQgZm9ybS4gRm9yIGRvY3VtZW50YXRpb24gc2VlOiBodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9AYXdzLXNkay9zMy1wcmVzaWduZWQtcG9zdCN1c2VyLWNvbnRlbnQtcG9zdC1maWxlLXVzaW5nLWh0bWwtZm9ybVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcG9zdFVybChidWNrZXQ6IHN0cmluZywga2V5OiBzdHJpbmcsIGV4cGlyZXM6IG51bWJlciA9IDM2MDAsIG1heFNpemU6IG51bWJlciA9IDEwMjQgKiAxMDI0ICogMTAwKTpcbiAgUHJvbWlzZTx7IHVybDogc3RyaW5nLCBmaWVsZHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47IH0+IHtcbiAgY29uc3QgeyB1cmwsIGZpZWxkcyB9ID0gYXdhaXQgY3JlYXRlUHJlc2lnbmVkUG9zdChjbGllbnQsIHtcbiAgICBCdWNrZXQ6IGJ1Y2tldCxcbiAgICBLZXk6IHRpZHkoa2V5KSxcbiAgICBFeHBpcmVzOiBleHBpcmVzLFxuICAgIENvbmRpdGlvbnM6IFtcbiAgICAgIFsnY29udGVudC1sZW5ndGgtcmFuZ2UnLCAwLCBtYXhTaXplXSwgLy8gMTAwTSAtIHNob3VsZCBiZSBwbGVudHkgb2YgaGVhZHJvb21cbiAgICBdLFxuICB9KTtcblxuICByZXR1cm4ge1xuICAgIHVybCxcbiAgICBmaWVsZHMsXG4gIH07XG59XG4iXX0=