S3-संगत बकेट में स्टोरेज ऑफलोड करना
API को स्टेटलेस और स्केलेबल बनाए रखने के लिए प्री-साइन किए गए URL से अपलोड सीधे S3/MinIO में स्ट्रीम कीजिए।
S3-संगत बकेट में स्टोरेज ऑफलोड करना, CoddyKit पर FastAPI बैकएंड डेवलपमेंट बूटकैंप का एक निःशुल्क पाठ है। यह 4 में से 3वाँ पाठ है। इस अध्ययन पथ के 3 तक कोई भी पाठ पूरा पढ़ना निःशुल्क है — इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ व्यावहारिक अभ्यास भी उपलब्ध कराता है। यह FastAPI बैकएंड डेवलपमेंट बूटकैंप सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
स्टोरेज को S3 पर क्यों स्थानांतरित करें?
अपलोड की गई फ़ाइलों को अपने API सर्वर की स्थानीय डिस्क पर रखना बड़े पैमाने पर काम नहीं करता। हर प्रतिकृति को अपनी अलग कॉपी चाहिए होगी, डिस्क भर जाएँगी और कंटेनर अल्पकालिक होते हैं — पॉड को पुनः प्रारंभ करते ही फ़ाइलें गायब हो जाएँगी।
समाधान है मीडिया को बाहरी ऑब्जेक्ट स्टोर में भेजना और अपने API को स्टेटलेस रखना। कोई भी S3-संगत सेवा काम करेगी:
- Amazon S3 — मूल और पूरी तरह प्रबंधित सेवा।
- MinIO — स्वयं-होस्टेड, S3 API-संगत और विकास तथा स्थानीय परिसर के लिए उपयोगी।
- Cloudflare R2, Backblaze B2, DigitalOcean Spaces — कम egress लागत और वही API।
क्योंकि ये सभी S3 प्रोटोकॉल पर काम करती हैं, इसलिए केवल endpoint URL बदलकर वही boto3 क्लाइंट कोड इनमें से किसी को भी लक्ष्य बना सकता है।
boto3 S3 क्लाइंट को कॉन्फ़िगर करना
boto3 लाइब्रेरी Python के लिए मानक AWS SDK है। MinIO या R2 जैसे गैर-AWS प्रदाता को लक्ष्य बनाने के लिए स्पष्ट endpoint_url दें।
क्रेडेंशियल और एंडपॉइंट को सेटिंग्स में रखें, कोड में कभी सीधे न लिखें। config=Config(signature_version="s3v4") का उपयोग करें, ताकि presigned URL आधुनिक SigV4 एल्गोरिदम से बनाए जाएँ, जिसे सभी प्रदाता स्वीकार करते हैं।
import boto3
from botocore.config import Config
def build_s3_client():
return boto3.client(
"s3",
endpoint_url="https://s3.eu-central-1.amazonaws.com",
aws_access_key_id="AKIA...",
aws_secret_access_key="secret...",
region_name="eu-central-1",
config=Config(signature_version="s3v4"),
)
client = build_s3_client()
print(type(client).__name__)सरल तरीका (और इसकी समस्या)
पहला स्पष्ट प्रयास पूरे अपलोड को मेमोरी में पढ़कर S3 को सौंपना है:
data = await file.read()पूरी फ़ाइल को RAM में लोड करता है।- 2 GB का वीडियो अपलोड प्रक्रिया की मेमोरी में 2 GB जोड़ देता है — समकालिक अनुरोधों की संख्या बढ़ने पर आपके worker OOM के कारण क्रैश हो जाते हैं।
यह छोटे अवतारों के लिए ठीक है, लेकिन मीडिया के लिए जोखिमपूर्ण है। हमें API के माध्यम से बाइटों को स्ट्रीम करना चाहिए (या presigned URL से API को पूरी तरह हटाना चाहिए)। अगले भागों में दोनों तकनीकें बनाई जाएँगी।
from fastapi import FastAPI, UploadFile
app = FastAPI()
@app.post("/upload-naive")
async def upload_naive(file: UploadFile):
data = await file.read() # whole file in RAM - avoid for large media!
return {"size": len(data)}upload_fileobj से अपलोड स्ट्रीम करना
FastAPI का UploadFile एक SpooledTemporaryFile को लपेटता है: छोटे अपलोड मेमोरी में रहते हैं और बड़े अपलोड अपने-आप डिस्क पर चले जाते हैं। इसकी .file विशेषता एक सामान्य फ़ाइल-जैसी वस्तु होती है।
boto3 का upload_fileobj उस स्ट्रीम को हिस्सों में पढ़ता है और पर्दे के पीछे बहुखंडी अपलोड करता है — इसलिए फ़ाइल के आकार की परवाह किए बिना मेमोरी सीमित रहती है।
from fastapi import FastAPI, UploadFile
app = FastAPI()
BUCKET = "user-media"
@app.post("/upload")
async def upload(file: UploadFile):
client.upload_fileobj(
Fileobj=file.file, # streams in chunks, no full read
Bucket=BUCKET,
Key=f"uploads/{file.filename}",
ExtraArgs={"ContentType": file.content_type},
)
return {"key": f"uploads/{file.filename}"}इवेंट लूप को अवरुद्ध न करें
boto3 सिंक्रोनस है। किसी async def एंडपॉइंट के भीतर सीधे upload_fileobj को कॉल करने पर बाइटों के S3 तक पहुँचने के दौरान इवेंट लूप अवरुद्ध रहता है और उस worker के अन्य सभी अनुरोध रुक जाते हैं।
अवरोधक कॉल को run_in_threadpool (Starlette) या asyncio.to_thread की सहायता से थ्रेड पूल में भेजें। अब इवेंट लूप अन्य कनेक्शनों की सेवा के लिए खाली रहेगा।
from fastapi import FastAPI, UploadFile
from fastapi.concurrency import run_in_threadpool
app = FastAPI()
BUCKET = "user-media"
@app.post("/upload")
async def upload(file: UploadFile):
key = f"uploads/{file.filename}"
await run_in_threadpool(
client.upload_fileobj, file.file, BUCKET, key,
{"ContentType": file.content_type},
)
return {"key": key}Presigned URL: क्लाइंट को सीधे S3 से बात करने दें
API के माध्यम से स्ट्रीम करने पर भी आपकी बैंडविड्थ और CPU दो बार खर्च होते हैं (क्लाइंट→API, API→S3)। सबसे अधिक विस्तार योग्य तरीका presigned URL का उपयोग करके API को डेटा पथ से पूरी तरह हटाता है।
Presigned URL एक अस्थायी, हस्ताक्षरित लिंक है, जो एक ऑब्जेक्ट पर एक विशिष्ट ऑपरेशन (PUT या GET) की अनुमति देता है और N सेकंड बाद समाप्त हो जाता है। क्लाइंट सीधे S3 पर अपलोड करता है; आपका API केवल अनुरोध पर हस्ताक्षर करता है।
- API स्टेटलेस और छोटा रहता है — वह बाइटों को कभी छूता नहीं।
- क्रेडेंशियल सर्वर से बाहर नहीं जाते; हस्ताक्षर अनुमति को अपने भीतर समाहित रखता है।
Presigned PUT URL बनाना
अपलोड लिंक बनाने के लिए put_object क्लाइंट मेथड के साथ generate_presigned_url का उपयोग करें। एंडपॉइंट URL और अंतिम ऑब्जेक्ट कुंजी लौटाता है; इसके बाद ब्राउज़र फ़ाइल के मुख्य भाग के साथ उस URL पर साधारण HTTP PUT भेजता है।
छोटा ExpiresIn निर्धारित करें (जैसे 300–900 सेकंड) — अपलोड शुरू करने के लिए जितना आवश्यक हो, केवल उतना।
import uuid
from fastapi import FastAPI
app = FastAPI()
BUCKET = "user-media"
@app.post("/uploads/presign")
def presign_put(filename: str, content_type: str):
key = f"uploads/{uuid.uuid4()}-{filename}"
url = client.generate_presigned_url(
ClientMethod="put_object",
Params={"Bucket": BUCKET, "Key": key, "ContentType": content_type},
ExpiresIn=600,
)
return {"upload_url": url, "key": key}क्लाइंट-साइड अपलोड प्रवाह
Presigned PUT URL के साथ ब्राउज़र एक ही अनुरोध में अपलोड करता है — multipart फ़ॉर्म नहीं, केवल कच्चा मुख्य भाग। प्रवाह यह है:
- 1. क्लाइंट आपके API से presigned URL माँगता है (फ़ाइल नाम और सामग्री प्रकार भेजता है)।
- 2. API
upload_urlऔर अंतिमkeyलौटाता है। - 3. क्लाइंट फ़ाइल के बाइट और मिलते-जुलते
Content-Typeहेडर के साथPUT upload_urlकरता है। - 4. क्लाइंट आपके API को
keyकी सूचना देता है, ताकि आप उसे DB में सुरक्षित रख सकें।
PUT का Content-Type आपके द्वारा हस्ताक्षरित मान से मिलना ही चाहिए, अन्यथा S3 403 लौटाता है।
// Browser-side (illustrative)
const { upload_url, key } = await api.presign(file.name, file.type);
await fetch(upload_url, {
method: "PUT",
headers: { "Content-Type": file.type },
body: file,
});
await api.confirm(key);Presigned GET URL से निजी फ़ाइलें उपलब्ध कराना
डिफ़ॉल्ट रूप से बकेट को निजी रखें। किसी उपयोगकर्ता को फ़ाइल डाउनलोड या देखने देने के लिए ऑब्जेक्ट को सार्वजनिक बनाने के बजाय आवश्यकता पड़ने पर कम अवधि वाला presigned get_object URL बनाएँ।
इससे पहुँच आपके API के प्रमाणीकरण द्वारा नियंत्रित रहती है: जाँचें कि फ़ाइल उसी उपयोगकर्ता की है, फिर कुछ मिनटों के लिए मान्य URL पर हस्ताक्षर करें। उसे <img> src में शामिल करें या पुनर्निर्देशन के रूप में लौटाएँ।
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
BUCKET = "user-media"
@app.get("/files/{key:path}")
def download(key: str):
url = client.generate_presigned_url(
ClientMethod="get_object",
Params={"Bucket": BUCKET, "Key": key},
ExpiresIn=300,
)
return RedirectResponse(url)Presigned POST से अपलोड सीमित करना
Presigned PUT URL फ़ाइल का आकार सीमित नहीं कर सकता — कोई दुर्भावनापूर्ण क्लाइंट 50 GB की फ़ाइल अपलोड कर सकता है। जब आपको सर्वर द्वारा लागू सीमाओं की आवश्यकता हो, तो generate_presigned_post का उपयोग करें।
यह एक URL और फ़ॉर्म fields लौटाता है तथा content-length-range और सटीक सामग्री प्रकार जैसी शर्तें जोड़ने देता है। यदि बाइट नीति का उल्लंघन करते हैं, तो S3 सर्वर स्तर पर अपलोड अस्वीकार कर देता है।
from fastapi import FastAPI
app = FastAPI()
BUCKET = "user-media"
@app.post("/uploads/presign-post")
def presign_post(key: str, content_type: str):
return client.generate_presigned_post(
Bucket=BUCKET,
Key=key,
Fields={"Content-Type": content_type},
Conditions=[
{"Content-Type": content_type},
["content-length-range", 1, 10 * 1024 * 1024], # max 10 MB
],
ExpiresIn=600,
)पुनः उपयोग योग्य कुंजी बनाने वाला
ऑब्जेक्ट कुंजियाँ टकराव-रोधी और व्यवस्थित होनी चाहिए, और क्लाइंट के कच्चे फ़ाइल नाम पर कभी भरोसा नहीं करना चाहिए (उसमें ../ या असामान्य वर्ण हो सकते हैं)। एक छोटा सहायक इस तर्क को एक जगह रखता है और शुद्ध Python होता है — इसलिए इकाई परीक्षण करना आसान है।
एक अच्छी कुंजी में तार्किक उपसर्ग (मालिक, श्रेणी), विशिष्टता के लिए UUID और स्वच्छ किया हुआ एक्सटेंशन शामिल होता है।
import re
import uuid
def build_key(user_id: int, filename: str) -> str:
ext = filename.rsplit(".", 1)[-1].lower() if "." in filename else "bin"
ext = re.sub(r"[^a-z0-9]", "", ext)[:8] or "bin"
return f"users/{user_id}/{uuid.uuid4().hex}.{ext}"
print(build_key(42, "My Vacation.JPG"))
print(build_key(7, "../../etc/passwd"))
print(build_key(1, "noext"))त्वरित जाँच: विस्तार योग्य तरीका चुनना
आप ऐसा एंडपॉइंट बना रहे हैं, जो उपयोगकर्ताओं को 2 GB तक के बड़े वीडियो अपलोड करने देता है। आप चाहते हैं कि FastAPI सेवा स्टेटलेस रहे और फ़ाइल के बाइट API सर्वर से होकर बिल्कुल न गुजरें। कौन-सा तरीका सबसे उपयुक्त है?
पुनरावलोकन: बड़े पैमाने पर स्टेटलेस मीडिया
अब आपके पास S3-संगत बकेट में स्टोरेज स्थानांतरित करने के लिए पूरा टूलकिट है:
- एक क्लाइंट, अनेक प्रदाता —
endpoint_urlवालेboto3से S3, MinIO, R2 और Spaces को लक्ष्य बनाया जा सकता है। - पूरी फ़ाइलों को कभी बफ़र न करें — यदि बाइट API से होकर गुजरने ही हों, तो
upload_fileobjका उपयोग करें और उसेrun_in_threadpoolमें भेजें, ताकि इवेंट लूप खाली रहे। - Presigned URL को प्राथमिकता दें — क्लाइंट सीधे S3 पर PUT/GET करते हैं; API केवल हस्ताक्षर करता है और स्टेटलेस रहता है।
generate_presigned_postऔरcontent-length-rangeशर्त से सीमाएँ लागू करें।- बकेट निजी रखें और प्रमाणीकरण द्वारा नियंत्रित कम अवधि वाले presigned GET लिंक से फ़ाइलें उपलब्ध कराएँ।
- कुंजियों को स्वच्छ करें — UUID-आधारित और उपसर्गयुक्त कुंजियाँ बनाएँ, कच्चे फ़ाइल नामों पर कभी भरोसा न करें।
परिणामस्वरूप ऐसा API मिलता है, जो 2 GB और 2 KB दोनों के अपलोड को समान सीमित संसाधन-उपयोग के साथ संभालता है।
एआई शिक्षक के साथ FastAPI बैकएंड डेवलपमेंट बूटकैंप सीखें — निःशुल्क
अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।
- पाठ्यक्रम
- 21
- पाठ
- 84
अक्सर पूछे जाने वाले प्रश्न
क्या “S3-संगत बकेट में स्टोरेज ऑफलोड करना” पाठ निःशुल्क है?
हाँ — FastAPI बैकएंड डेवलपमेंट बूटकैंप अध्ययन पथ के 3 तक कोई भी पाठ, जिसमें “S3-संगत बकेट में स्टोरेज ऑफलोड करना” भी शामिल है, यहाँ वेब पर पूरा पढ़ना निःशुल्क है। इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ इंटरैक्टिव अभ्यास भी उपलब्ध कराता है। FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
“S3-संगत बकेट में स्टोरेज ऑफलोड करना” में मैं क्या सीखूँगा?
API को स्टेटलेस और स्केलेबल बनाए रखने के लिए प्री-साइन किए गए URL से अपलोड सीधे S3/MinIO में स्ट्रीम कीजिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ FastAPI बैकएंड डेवलपमेंट बूटकैंप का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।
क्या FastAPI बैकएंड डेवलपमेंट बूटकैंप शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?
पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर FastAPI बैकएंड डेवलपमेंट बूटकैंप शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 3वाँ पाठ है।
“S3-संगत बकेट में स्टोरेज ऑफलोड करना” पाठ पूरा करने में कितना समय लगता है?
CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।
क्या मैं इस FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ में कोड लिख और चला सकता हूँ?
हाँ। हर FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।
इस पाठ्यक्रम के सभी पाठ
- मल्टीपार्ट अपलोड और सामग्री सत्यापन
- स्ट्रीमिंग प्रतिक्रियाएँ और रेंज अनुरोध
- S3-संगत बकेट में स्टोरेज ऑफलोड करना
- अतुल्यकालिक छवि और दस्तावेज़ रूपांतरण