S3Client را در Node.js پیکربندی کنید
AWS SDK v3 ماژولار است؛ فقط Client، Commandها و Presigner موردنیاز نصب میشوند. این نمونه نشان میدهد چطور Endpoint سفارشی را تنظیم، Body دانلود را بهصورت Stream مصرف و برای GET و PUT لینک موقت تولید کنید.

برنامهٔ نمونه، هر عملیات را بهصورت یک زیرفرمان مستقل اجرا میکند. فایل آزمایشی زیر tutorial/ میرود تا با دادهٔ واقعی باکت قاطی نشود.
اگر از ابتدا پیش میروید، نقطهٔ شکست مشخص میماند. اجرای head یا download قبل از آپلود، بهدرستی 404 برمیگرداند.
پیشنیاز و نصب SDK
اول کتابخانه همین پوشه را نصب کنید. بدون این قدم، نمونه اجرا نمیشود.
(cd examples/javascript && npm install)examples/javascript/
├── .env # پس از کپیکردن فایل نمونه ساخته میشود
├── package.json # وابستگیهای Node.js
└── parspack_s3.js # Client و هفت فرمان مدیریت فایلساخت فایل .env
پنج مقدار را از پنل فضای ابری پارسپک کپی کنید. معنی هر متغیر و شکل معمول Endpoint در صفحه شروع آمده است.
upload با خطای امضا میخوابد.cp examples/.env.example examples/javascript/.envPARSPACK_S3_ENDPOINT=https://c123456.parspack.net
PARSPACK_S3_BUCKET=c123456
PARSPACK_S3_REGION=us-east-1
PARSPACK_S3_ACCESS_KEY=YOUR_ACCESS_KEY
PARSPACK_S3_SECRET_KEY=YOUR_SECRET_KEY| متغیر | چه چیزی در آن میگذارید | اگر اشتباه باشد |
|---|---|---|
PARSPACK_S3_ENDPOINT | آدرس HTTPS پنل، بدون / در انتها؛ شکل معمول https://c123456.parspack.net | Timeout یا خطای امضا |
PARSPACK_S3_BUCKET | نام باکت؛ اغلب با شناسه داخل Endpoint یکی است | NoSuchBucket |
PARSPACK_S3_REGION | فقط برای امضای Signature V4 است. اگر پنل Region نداد، us-east-1 را ثابت نگه دارید | SignatureDoesNotMatch |
PARSPACK_S3_ACCESS_KEY / SECRET_KEY | کلیدهای API از پنل؛ فقط روی سرور | AccessDenied یا خطای امضا |
فایل .env را Commit نکنید. Access Key و Secret Key فقط روی سرور میمانند؛ مرورگر فقط لینک کوتاهعمر میگیرد.
اتصال برنامه به فضای پارسپک
Client را یک بار با مقدارهای .env بسازید. همین شیء برای هر هفت فرمان کافی است.
Endpoint همان آدرس HTTPS پنل است؛ اسلش انتها را بردارید. Region موقعیت سرور نیست؛ اگر پنل چیزی نگفت us-east-1 را عوض نکنید. Path-style باید روشن باشد تا URL به شکل /bucket/key ساخته شود، نه bucket.endpoint.const endpoint = process.env.PARSPACK_S3_ENDPOINT.replace(/\/+$/u, "");
const client = new S3Client({
endpoint,
region: process.env.PARSPACK_S3_REGION,
credentials: {
accessKeyId: process.env.PARSPACK_S3_ACCESS_KEY,
secretAccessKey: process.env.PARSPACK_S3_SECRET_KEY,
},
forcePathStyle: true,
maxAttempts: 3,
});آپلود فایل با PutObjectCommand
اولین فرمان سناریو: فایل محلی را با یک نام مشخص در باکت بگذارید.
./hello.txt است؛ داخل باکت با نام tutorial/hello.txt ذخیره میشود. اسلش پوشه واقعی نمیسازد، فقط بخشی از نام است. ETag اثر انگشت محتواست. اگر همین نام از قبل در باکت باشد، محتوای قبلی عوض میشود.const file = await stat(localFile);
const result = await client.send(new PutObjectCommand({
Bucket: bucket,
Key: objectKey,
Body: createReadStream(localFile),
ContentLength: file.size,
ContentType: contentTypeFor(localFile),
}));
console.log(result.ETag);| پارامتر | مثال | کاربرد |
|---|---|---|
Bucket | از .env | محل ذخیره Object |
Key | tutorial/hello.txt | نام کامل Object در S3 |
Body | createReadStream | جریان بایتهای فایل محلی |
ContentType | text/plain | نوع محتوای فایل |
node examples/javascript/parspack_s3.js upload ./hello.txt tutorial/hello.txtاگر tutorial/hello.txt از قبل وجود داشته باشد، Upload جدید همان Key را جایگزین میکند.
فهرست فایلها و مشخصات یک فایل
بعد از آپلود، اول ببینید فایل در فهرست هست؛ بعد حجم و نوع را بدون دانلود بخوانید.
list tutorial/ خود فایل را نمیآورد؛ فقط نام، حجم و زمان تغییر فایلهایی را برمیگرداند که با این Prefix شروع میشوند. اگر آرایه خالی بود، یا آپلود انجام نشده یا Prefix را اشتباه نوشتهاید.head وقتی لازم است که فقط بخواهید بدانید فایل هست یا نه، یا حجم و نوعش چیست. اگر Key نباشد معمولاً 404 میگیرید. این فرمان را با دانلود عوض نکنید؛ بدنه فایل را منتقل نمیکند.for await (const page of paginateListObjectsV2(
{ client },
{ Bucket: bucket, Prefix: "tutorial/" },
)) {
for (const object of page.Contents ?? []) {
console.log(object.Key, object.Size, object.LastModified?.toISOString());
}
}node examples/javascript/parspack_s3.js list tutorial/const info = await client.send(
new HeadObjectCommand({ Bucket: bucket, Key: objectKey }),
);
console.log(info.ContentLength, info.ContentType, info.ETag);node examples/javascript/parspack_s3.js head tutorial/hello.txttutorial/ بگذارید، فقط فایلهایی که نامشان با این مقدار شروع میشود دیده میشوند.Contents وجود نداشته باشد؛ با ?? [] از خطا جلوگیری کنید.دانلود روی سرور
فایل را از باکت بگیرید و روی دیسک همین برنامه بنویسید. این کار لینک برای کاربر نمیسازد.
const result = await client.send(
new GetObjectCommand({ Bucket: bucket, Key: objectKey }),
);
await pipeline(result.Body, createWriteStream("./downloads/hello.txt"));node examples/javascript/parspack_s3.js download tutorial/hello.txt ./downloads/hello.txtلینک موقت دانلود برای کاربر
این فرمان را با دانلود روی سرور قاطی نکنید. اینجا فایل روی دیسک شما نوشته نمیشود؛ فقط یک آدرس زماندار ساخته میشود. جریان کامل در صفحه شروع است.
<a href> بگذارید، یا با curl --output file.pdf "$URL" بگیرید. Header اضافه لازم نیست. 900 یعنی پانزده دقیقه؛ بعد از آن آدرس کار نمیکند.const downloadUrl = await getSignedUrl(
client,
new GetObjectCommand({ Bucket: bucket, Key: objectKey }),
{ expiresIn: 900 },
);node examples/javascript/parspack_s3.js presign-get tutorial/hello.txt 900curl --output invoice.pdf "$SIGNED_DOWNLOAD_URL"لینک را کوتاه نگه دارید؛ بین ۱ ثانیه تا ۷ روز (۶۰۴۸۰۰ ثانیه). فقط همان Key را میخواند. لینک را فقط بعد از ورود کاربر و چک مجوز بسازید.
لینک موقت آپلود مستقیم
کاربر فایل را از مرورگر به باکت میفرستد. فایل از سرور شما رد نمیشود و کلید API هم به کاربر نمیرسد.
Content-Type را دقیقاً همان مقدار زمان ساخت لینک بگذارید؛ وگرنه معمولاً خطای امضا میگیرید. از مرورگر فقط وقتی کار میکند که CORS باکت سایت شما را مجاز کرده باشد؛ وگرنه از curl یا سرور خودتان استفاده کنید.const contentType = "text/plain";
const uploadUrl = await getSignedUrl(
client,
new PutObjectCommand({ Bucket: bucket, Key: objectKey, ContentType: contentType }),
{ expiresIn: 900, signableHeaders: new Set(["content-type"]) },
);node examples/javascript/parspack_s3.js presign-put tutorial/upload.txt text/plain 900curl --request PUT \
--header 'Content-Type: text/plain' \
--upload-file ./hello.txt \
"$SIGNED_UPLOAD_URL"await fetch(signed.url, {
method: "PUT",
headers: { "Content-Type": signed.headers["Content-Type"] },
body: file,
});| Presigned GET | Presigned PUT | |
|---|---|---|
| Method | GET | PUT |
| ورودی امضا | Bucket، Key، انقضا | Bucket، Key، Content-Type، انقضا |
| جایگزین کدام فرمان سرور است | جایگزین download برای کاربر نهایی | جایگزین upload وقتی فایل نباید از سرور شما عبور کند |
اگر موقع ساخت لینک text/plain گذاشتهاید، هنگام ارسال هم باید همان را بفرستید. از مرورگر این کار فقط وقتی درست است که CORS باکت سایت شما را مجاز کرده باشد؛ وگرنه از curl یا سرور خودتان استفاده کنید.
حذف فایل با DeleteObjectCommand
نام را از باکت برمیدارد. لازم نیست اول دانلودش کنید. فایل روی سیستم شما دست نمیخورد.
await client.send(
new DeleteObjectCommand({ Bucket: bucket, Key: objectKey }),
);node examples/javascript/parspack_s3.js delete tutorial/hello.txtخطای SDK را با metadata بخوانید
نمونه نام و پیام خطا را روی stderr مینویسد و با کد غیرصفر تمام میشود. اگر SDK پاسخ گرفته باشد، Status Code داخل metadata کمک میکند خطای سرویس را از مشکل شبکه جدا کنید.
catch (error) {
console.error(error instanceof Error ? `${error.name}: ${error.message}` : error);
process.exitCode = 1;
}| خطا | علت معمول | بررسی |
|---|---|---|
Local file not found | مسیر فایل محلی اشتباه است | مسیر را نسبت به Terminal بررسی کنید |
AccessDenied | کلید یا دسترسی Bucket کافی نیست | مقدارهای پنل و نوع دسترسی کاربر فضای ابری |
SignatureDoesNotMatch | امضای درخواست با تنظیمات یکی نیست | Slash انتهای Endpoint، Region، کلیدها و Content-Type در PUT |
NoSuchBucket | نام Bucket با مقدار پنل یکی نیست | PARSPACK_S3_BUCKET |
Timeout / connection | Endpoint در دسترس نیست یا HTTPS قطع است | آدرس پنل را بدون تغییر و بدون / انتها وارد کنید |
اجرای کامل همین سناریو
کد همراه مستندات، Loader فایل .env، اعتبارسنجی ورودی، تشخیص Content-Type و خروجی JSON را یکجا دارد. اگر خروجی هر فرمان شبیه نمونههای بالا بود، میتوانید Key و مسیر را با نام فایلهای برنامه خودتان عوض کنید.
(cd examples/javascript && npm install)
cp examples/.env.example examples/javascript/.env
# مقدارهای .env را کامل کنید
printf 'hello ParsPack\n' > hello.txt
node examples/javascript/parspack_s3.js upload ./hello.txt tutorial/hello.txt
node examples/javascript/parspack_s3.js list tutorial/
node examples/javascript/parspack_s3.js head tutorial/hello.txt
node examples/javascript/parspack_s3.js download tutorial/hello.txt ./downloads/hello.txt
node examples/javascript/parspack_s3.js presign-get tutorial/hello.txt 900
node examples/javascript/parspack_s3.js presign-put tutorial/upload.txt text/plain 900
node examples/javascript/parspack_s3.js delete tutorial/hello.txt