1import type { APIRoute } from "astro";
2import { API } from "../../utils/api";
34interface MultipartUploadRequest {
56789interface CompleteMultipartRequest {
101112131415// Creates and completes a new multipart upload session
16export const POST: APIRoute = async ({ request, locals }) => {
17 // Set the origin for the API
18 API.init(locals.runtime.env.ORIGIN);
1920 // Handle CORS preflight requests
21 if (request.method === "OPTIONS") {
22 console.log("CORS preflight request from:", request.headers.get("Origin"));
23 return API.cors(request);
24252627 // Check if bucket is available
28 const bucket = locals.runtime.env.CLOUD_FILES;
2930 return API.error("Cloud storage not configured", request, 500);
313233 const url = new URL(request.url);
34 const action = url.searchParams.get("action");
353637 return API.error("Missing action parameter", request, 400);
3839404142 // Create a new multipart upload
43 const body: MultipartUploadRequest = await request.json();
444546 return API.error("Missing key parameter", request, 400);
47484950 const multipartUpload = await bucket.createMultipartUpload(body.key, {
51 httpMetadata: body.contentType
5253 contentType: body.contentType,
5455565758596061 key: multipartUpload.key,
62 uploadId: multipartUpload.uploadId,
6364656667 console.error("Failed to create multipart upload:", error);
68 return API.error("Failed to create multipart upload", request, 500);
6970717273 // Complete a multipart upload
74 const body: CompleteMultipartRequest = await request.json();
7576 if (!body.uploadId || !body.key || !body.parts) {
77 return API.error("Missing required parameters", request, 400);
78798081 const multipartUpload = bucket.resumeMultipartUpload(
8283848586 // Parts are already in R2UploadedPart format
87 const r2Parts = body.parts;
8889 const object = await multipartUpload.complete(r2Parts);
90919293949596979899100101 console.error("Failed to complete multipart upload:", error);
102103 error.message || "Failed to complete multipart upload",
104105106107108109110111 return API.error(`Unknown action: ${action}`, request, 400);
112113114 console.error("Multipart upload error:", error);
115 return API.error("Multipart upload failed", request, 500);
116117118119// Uploads individual parts of a multipart upload
120export const PUT: APIRoute = async ({ request, locals }) => {
121 // Set the origin for the API
122 API.init(locals.runtime.env.ORIGIN);
123124 // Handle CORS preflight requests
125 if (request.method === "OPTIONS") {
126 console.log("CORS preflight request from:", request.headers.get("Origin"));
127 return API.cors(request);
128129130131 // Check if bucket is available
132 const bucket = locals.runtime.env.CLOUD_FILES;
133134 return API.error("Cloud storage not configured", request, 500);
135136137 const url = new URL(request.url);
138 const action = url.searchParams.get("action");
139140 if (action !== "upload-part") {
141 return API.error(`Unknown action: ${action}`, request, 400);
142143144 const uploadId = url.searchParams.get("uploadId");
145 const partNumberStr = url.searchParams.get("partNumber");
146 const key = url.searchParams.get("key");
147148 if (!uploadId || !partNumberStr || !key) {
149 return API.error("Missing uploadId, partNumber, or key", request, 400);
150151152 const partNumber = parseInt(partNumberStr);
153 if (isNaN(partNumber) || partNumber < 1) {
154 return API.error("Invalid part number", request, 400);
155156157158 return API.error("Missing request body", request, 400);
159160161162 const multipartUpload = bucket.resumeMultipartUpload(key, uploadId);
163164 // Convert request body to ArrayBuffer to get known length
165 const arrayBuffer = await request.arrayBuffer();
166 const uploadedPart = await multipartUpload.uploadPart(
167168169170171172173174 partNumber: uploadedPart.partNumber,
175176177178179180 console.error("Failed to upload part:", error);
181 return API.error(error.message || "Failed to upload part", request, 400);
182183184 console.error("Upload part error:", error);
185 return API.error("Upload part failed", request, 500);
186187188189// Aborts a multipart upload
190export const DELETE: APIRoute = async ({ request, locals }) => {
191 // Set the origin for the API
192 API.init(locals.runtime.env.ORIGIN);
193194 // Handle CORS preflight requests
195 if (request.method === "OPTIONS") {
196 console.log("CORS preflight request from:", request.headers.get("Origin"));
197 return API.cors(request);
198199200201 // Check if bucket is available
202 const bucket = locals.runtime.env.CLOUD_FILES;
203204 return API.error("Cloud storage not configured", request, 500);
205206207 const url = new URL(request.url);
208 const action = url.searchParams.get("action");
209210 if (action !== "abort") {
211 return API.error(`Unknown action: ${action}`, request, 400);
212213214 const uploadId = url.searchParams.get("uploadId");
215 const key = url.searchParams.get("key");
216217218 return API.error("Missing uploadId or key", request, 400);
219220221222 const multipartUpload = bucket.resumeMultipartUpload(key, uploadId);
223 await multipartUpload.abort();
224225226227228 message: "Multipart upload aborted successfully",
229230231232233 console.error("Failed to abort multipart upload:", error);
234235 error.message || "Failed to abort multipart upload",
236237238239240241 console.error("Abort multipart upload error:", error);
242 return API.error("Abort multipart upload failed", request, 500);
243244245246export const OPTIONS: APIRoute = async ({ request, locals }) => {
247 // Set the origin for the API
248 API.init(locals.runtime.env.ORIGIN);
249 return API.cors(request);
250