ප්‍රධාන අන්තර්ගතයට පනින්න

Cloud Storage

ඔබගේ server හරහා proxy නොකර cloud storage සපයන්නන් වෙත ගොනු සෘජුව upload කරන්න.

Amazon S3

ස්ථාපනය

npm install @samithahansaka/dropup

මූලික භාවිතය

import { useDropup } from '@samithahansaka/dropup';
import { createS3Uploader } from '@samithahansaka/dropup/cloud/s3';

function S3Uploader() {
const { files, actions, getDropProps, getInputProps } = useDropup({
upload: createS3Uploader({
getPresignedUrl: async (file) => {
// Presigned URL ලබා ගැනීමට ඔබගේ backend එක call කරන්න
const response = await fetch('/api/s3/presign', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filename: file.name,
contentType: file.type,
}),
});
return response.json();
},
}),

onUploadComplete: (file) => {
console.log('S3 වෙත upload විය:', file.uploadedUrl);
},
});

return (
<div {...getDropProps()}>
<input {...getInputProps()} />
<p>S3 වෙත upload කිරීමට ගොනු දමන්න</p>
</div>
);
}

Backend: Presigned URL සෑදීම

// Node.js / Express උදාහරණය
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

const s3 = new S3Client({
region: process.env.AWS_REGION,
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
});

app.post('/api/s3/presign', async (req, res) => {
const { filename, contentType } = req.body;
const key = `uploads/${Date.now()}-${filename}`;

const command = new PutObjectCommand({
Bucket: process.env.S3_BUCKET,
Key: key,
ContentType: contentType,
});

const url = await getSignedUrl(s3, command, { expiresIn: 3600 });

res.json({
url,
fields: {}, // සරල PUT සඳහා අතිරේක fields අවශ්‍ය නැත
});
});

S3 POST සමඟ (Multipart Form)

S3 POST policies සඳහා:

createS3Uploader({
getPresignedUrl: async (file) => {
const response = await fetch('/api/s3/presign-post', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filename: file.name,
contentType: file.type,
}),
});

const { url, fields } = await response.json();

return {
url, // S3 bucket URL
fields, // Form එකට ඇතුළත් කළ යුතු Policy fields
};
},
});

Google Cloud Storage

import { createGCSUploader } from '@samithahansaka/dropup/cloud/gcs';

function GCSUploader() {
const { files, getDropProps, getInputProps } = useDropup({
upload: createGCSUploader({
getSignedUrl: async (file) => {
const response = await fetch('/api/gcs/sign', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filename: file.name,
contentType: file.type,
}),
});
return response.json();
},
}),
});

return (
<div {...getDropProps()}>
<input {...getInputProps()} />
<p>Google Cloud Storage වෙත upload කරන්න</p>
</div>
);
}

Backend: GCS Signed URL

// Node.js උදාහරණය
import { Storage } from '@google-cloud/storage';

const storage = new Storage();
const bucket = storage.bucket(process.env.GCS_BUCKET);

app.post('/api/gcs/sign', async (req, res) => {
const { filename, contentType } = req.body;
const blob = bucket.file(`uploads/${Date.now()}-${filename}`);

const [url] = await blob.getSignedUrl({
version: 'v4',
action: 'write',
expires: Date.now() + 15 * 60 * 1000, // විනාඩි 15
contentType,
});

res.json({ url });
});

Azure Blob Storage

import { createAzureUploader } from '@samithahansaka/dropup/cloud/azure';

function AzureUploader() {
const { files, getDropProps, getInputProps } = useDropup({
upload: createAzureUploader({
getSasUrl: async (file) => {
const response = await fetch('/api/azure/sas', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filename: file.name,
contentType: file.type,
}),
});
return response.json();
},
}),
});

return (
<div {...getDropProps()}>
<input {...getInputProps()} />
<p>Azure Blob Storage වෙත upload කරන්න</p>
</div>
);
}

Backend: Azure SAS URL

// Node.js උදාහරණය
import {
BlobServiceClient,
generateBlobSASQueryParameters,
BlobSASPermissions,
} from '@azure/storage-blob';

const blobServiceClient = BlobServiceClient.fromConnectionString(
process.env.AZURE_STORAGE_CONNECTION_STRING
);

app.post('/api/azure/sas', async (req, res) => {
const { filename, contentType } = req.body;
const containerClient = blobServiceClient.getContainerClient('uploads');
const blobName = `${Date.now()}-${filename}`;
const blobClient = containerClient.getBlockBlobClient(blobName);

const sasToken = generateBlobSASQueryParameters(
{
containerName: 'uploads',
blobName,
permissions: BlobSASPermissions.parse('cw'), // Create, Write
expiresOn: new Date(Date.now() + 15 * 60 * 1000),
},
blobServiceClient.credential
).toString();

res.json({
url: `${blobClient.url}?${sasToken}`,
headers: {
'x-ms-blob-type': 'BlockBlob',
'Content-Type': contentType,
},
});
});

Cloudflare R2

R2 යනු S3-compatible වේ, එබැවින් S3 uploader භාවිතා කරන්න:

import { createS3Uploader } from '@samithahansaka/dropup/cloud/s3';

function R2Uploader() {
const { files, getDropProps, getInputProps } = useDropup({
upload: createS3Uploader({
getPresignedUrl: async (file) => {
const response = await fetch('/api/r2/presign', {
method: 'POST',
body: JSON.stringify({ filename: file.name }),
});
return response.json();
},
}),
});

return (
<div {...getDropProps()}>
<input {...getInputProps()} />
<p>Cloudflare R2 වෙත upload කරන්න</p>
</div>
);
}

Backend: R2 Presigned URL

import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

const s3 = new S3Client({
region: 'auto',
endpoint: `https://${process.env.CF_ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
},
});

app.post('/api/r2/presign', async (req, res) => {
const { filename } = req.body;

const command = new PutObjectCommand({
Bucket: process.env.R2_BUCKET,
Key: `uploads/${Date.now()}-${filename}`,
});

const url = await getSignedUrl(s3, command, { expiresIn: 3600 });
res.json({ url });
});

DigitalOcean Spaces

මෙයද S3-compatible වේ:

// S3 මෙන්ම, ඔබගේ backend endpoint config යාවත්කාලීන කරන්න
const s3 = new S3Client({
region: 'nyc3',
endpoint: 'https://nyc3.digitaloceanspaces.com',
credentials: {
accessKeyId: process.env.DO_SPACES_KEY,
secretAccessKey: process.env.DO_SPACES_SECRET,
},
});

Custom Cloud Provider

ඕනෑම cloud service එකක් සඳහා ඔබගේම uploader සාදන්න:

import { useDropup, type CustomUploader } from '@samithahansaka/dropup';

const customCloudUploader: CustomUploader = async (file, options) => {
// 1. ඔබගේ backend එකෙන් upload URL ලබා ගන්න
const { uploadUrl, fileUrl } = await fetch('/api/custom-cloud/init', {
method: 'POST',
body: JSON.stringify({ filename: file.name, size: file.size }),
}).then(r => r.json());

// 2. ගොනුව upload කරන්න
const xhr = new XMLHttpRequest();

return new Promise((resolve, reject) => {
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
options.onProgress((e.loaded / e.total) * 100);
}
};

xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve({ url: fileUrl });
} else {
reject(new Error('Upload අසාර්ථකයි'));
}
};

xhr.onerror = () => reject(new Error('Network දෝෂය'));

// අවලංගු කිරීම හසුරුවන්න
options.signal.addEventListener('abort', () => xhr.abort());

xhr.open('PUT', uploadUrl);
xhr.send(file.file);
});
};

function CustomCloudUploader() {
const { files, getDropProps, getInputProps } = useDropup({
upload: customCloudUploader,
});

return (
<div {...getDropProps()}>
<input {...getInputProps()} />
<p>Custom cloud වෙත upload කරන්න</p>
</div>
);
}

ආරක්ෂණ හොඳම පරිචයන්

  1. Client එකේ credentials expose නොකරන්න - සෑම විටම backend එකේ signed URLs සාදන්න
  2. කෙටි expiration times භාවිතා කරන්න - සාමාන්‍යයෙන් විනාඩි 5-15 ප්‍රමාණවත්
  3. Backend එකේ ගොනු වර්ග validate කරන්න - Client-side validation පමණක් විශ්වාස නොකරන්න
  4. ඔබගේ cloud storage එකේ සුදුසු CORS policies සකසන්න
  5. Presigned URL policies වල ගොනු ප්‍රමාණ සීමා කරන්න
  6. User uploads සහ application assets සඳහා වෙනම buckets භාවිතා කරන්න