MCPcopy Create free account
hub / github.com/ScattrdBlade/bigFileUpload / uploadToS3

Function uploadToS3

utils/s3.ts:99–224  ·  view source on GitHub ↗
(
    fileBlob: Blob,
    filename: string,
    native: PluginNative<typeof import("../native")> | null,
    uploadRequest: UploadRequest
)

Source from the content-addressed store, hash-verified

97}
98
99export async function uploadToS3(
100 fileBlob: Blob,
101 filename: string,
102 native: PluginNative<typeof import("../native")> | null,
103 uploadRequest: UploadRequest
104): Promise<string> {
105 const {
106 s3Endpoint,
107 s3Bucket,
108 s3Region = "auto",
109 s3AccessKeyId,
110 s3SecretAccessKey,
111 s3SessionToken,
112 s3PublicUrl,
113 s3Prefix,
114 s3ForcePathStyle = true
115 } = settings.store as S3Store;
116
117 if (!s3Endpoint || !s3Bucket || !s3Region || !s3AccessKeyId || !s3SecretAccessKey) {
118 throw new Error("S3 endpoint, bucket, region, access key ID, and secret key are required");
119 }
120
121 const endpoint = new URL(s3Endpoint);
122 if (!/^https?:$/.test(endpoint.protocol)) {
123 throw new Error("S3 endpoint must be a valid HTTP(S) URL");
124 }
125
126 const extension = filename.includes(".") ? filename.slice(filename.lastIndexOf(".")) : "";
127 const prefixSegments = (s3Prefix || "").split("/").filter(Boolean);
128 const objectName = `${Date.now()}-${makeRandomHex(8)}${extension}`;
129 const objectKeyRaw = [...prefixSegments, objectName].join("/");
130 const objectKeyPath = objectKeyRaw.split("/").filter(Boolean).map(encodeRfc3986).join("/");
131
132 const host = s3ForcePathStyle ? endpoint.host : `${s3Bucket}.${endpoint.host}`;
133 const canonicalUri = s3ForcePathStyle
134 ? buildS3Path(endpoint.pathname, s3Bucket, objectKeyRaw)
135 : buildS3Path(endpoint.pathname, objectKeyRaw);
136
137 const uploadUrl = new URL(endpoint.toString());
138 uploadUrl.host = host;
139 uploadUrl.pathname = canonicalUri;
140 uploadUrl.search = "";
141
142 const now = new Date();
143 const { amzDate, dateStamp } = getTimestampParts(now);
144 const payloadHash = await sha256Hex(await fileBlob.arrayBuffer());
145
146 const canonicalHeadersMap: Record<string, string> = {
147 "content-type": fileBlob.type || "application/octet-stream",
148 "host": host,
149 "x-amz-content-sha256": payloadHash,
150 "x-amz-date": amzDate
151 };
152
153 if (s3SessionToken) {
154 canonicalHeadersMap["x-amz-security-token"] = s3SessionToken;
155 }
156

Callers 1

uploadToServiceFunction · 0.90

Calls 8

toProxiedUrlFunction · 0.90
buildS3PathFunction · 0.85
getTimestampPartsFunction · 0.85
sha256HexFunction · 0.85
hmacSha256Function · 0.85
toHexFunction · 0.85
textMethod · 0.80
makeRandomHexFunction · 0.70

Tested by

no test coverage detected