مایم net/mime
نوع رسانهی پروندهها، سرآیند Content-Type و بدنهی چندبخشی فرم.
واردسازی شبکه.مایم
نوع رسانه (MIME) به مرورگر و برنامهها میگوید محتوا چیست، مثل image/png. این بسته نوع را از پسوند پرونده پیدا میکند و سرآیند Content-Type را میخواند.
فرمهایی که پرونده بارگذاری میکنند بدنهی multipart/form-data میفرستند: چند بخش با یک مرز میانشان. تجزیه چندبخشی آن را میخواند و نویسنده چندبخشی آن را میسازد.
این بسته متن وضعیت را هم دارد، یعنی عبارت استاندارد هر کد وضعیت HTTP. بستهی اچ تی تی پی آن را به کار میبرد و معمولاً همانجاست که با این تابعها روبهرو میشوید.
اشتباههای رایج
- جدول نوعها کوتاه است.
پسوند مایمحدود ۲۵ پسوند را میشناسد:html htm css js mjs json map png jpg jpeg gif svg ico webp txt md pdf xml wasm zip mp4 webm mp3 wav woff woff2. هر چیز دیگری، از جملهcsv،avif،ttfوdocx،application/octet-streamمیشود؛ پس نوعهای دیگری را که پایگاهتان میفرستد پیش از صدا زدن آن خودتان رسیدگی کنید. - جستجو و مقایسه به بزرگی و کوچکی حروف حساساند.
رده مایمپسوند را کوچک نمیکند،تجزیه نوع محتوابزرگی و کوچکی نوع رسانه و نام پارامترها را نگه میدارد ودریافت پارامترنام را دقیقاً مقایسه میکند، پسCharset=UTF-8با"charset"پیدا نمیشود. پیش از مقایسه هر دو طرف را کوچک کنید. - فقط سه نوع charset میگیرند:
text/html،text/plainوtext/markdownباcharset=utf-8میآیند؛ CSS و جاوااسکریپت نه. - بارگذاری دودویی خود بایتها را لازم دارد.
تجزیه چندبخشیروی حافظهی خام کار میکند و بدنهی هر بخش را در یکبافر بایتنگه میدارد، ولی اگر بدنهی درخواست در راه از یکرشتهگذشته باشد، از پیش در نخستین بایت صفر بریده شده است.
راهنمای زیر جاهایی را نشان میدهد که یک برنامهی وب با نوع رسانه سروکار دارد: فرستادن پرونده با Content-Type درست، تصمیم دربارهی خواندن بدنهی درخواست، و بارگذاری پرونده در هر دو سمت.
Content-Type درست برای هر پرونده
مرورگر از روی Content-Type پاسخ تصمیم میگیرد با آن چه کند، نه از روی نام پرونده؛ پس برگهی سبکی که با application/octet-stream فرستاده شود نادیده گرفته میشود. رده مایم نام پرونده را از روی پسوندش به نوع آن میرساند، برای HTML، متن ساده و Markdown charset=utf-8 را هم میافزاید و برای نامهایی که نمیشناسد application/octet-stream برمیگرداند. پسوند مایم همین کار را برای یک پسوند تنها و بدون نقطه، مثل png، انجام میدهد؛ برای وقتی که نام پرونده در دست نیست.
واردسازی شبکه.مایم
واردسازی رشته
تابع سرآیند برای(مسیر: رشته): رشته:
برگشت "Content-Type: " + مایم.رده مایم(رشته.کوچک(مسیر))
پایان
تابع ریشه:
پروندهها := ["index.html"، "app.js"، "style.css"، "logo.svg"، "photo.JPG"، "fonts/vazir.woff2"، "report.pdf"، "data.bin"، "README"]
هر پ در پروندهها:
سرچاپ پ، "->"، سرآیند برای(پ)
پایان
سرچاپ مایم.رده مایم("photo.JPG")، "(بدون کوچک کردن)"
پایاناین جستجو به بزرگی و کوچکی حرف حساس است: photo.JPG فقط پس از lower() شناخته میشود. پروندههای دوربین و ویندوز اغلب پسوند با حرف بزرگ دارند، پس پیش از جستجو نام را کوچک کنید.
خواندن Content-Type درخواست
سرور باید پیش از خواندن بدنه به سرآیند Content-Type نگاه کند: JSON، فرم کدگذاریشده در نشانی و بارگذاری چندبخشی هر کدام جور دیگری خوانده میشوند. تجزیه نوع محتوا سرآیند را به media_type و پارامترهایش جدا میکند و دریافت پارامتر یک پارامتر، مثل charset یا boundary، را بدون نقلقول برمیگرداند و اگر نباشد رشتهی خالی.
واردسازی شبکه.مایم
واردسازی رشته
تابع توصیف(سرآیند: رشته): رشته:
نم := مایم.تجزیه نوع محتوا(سرآیند)
رسانه := رشته.کوچک(نم.نوع رسانه)
ناپایا نویسهگان := مایم.دریافت پارامتر(نم، "charset")
اگر نویسهگان.طول() == ۰: نویسهگان = "ندارد" پایان
اگر رسانه == "application/json":
برگشت "بدنه جیسون، نویسهگان " + نویسهگان
وگرنه رسانه == "application/x-www-form-urlencoded":
برگشت "فرم کدگذاریشده در نشانی"
وگرنه رسانه == "multipart/form-data":
برگشت "بارگذاری، مرز " + مایم.دریافت پارامتر(نم، "boundary")
وگرنه رسانه.بیاب("text/") == ۰:
برگشت "متن ساده، نویسهگان " + نویسهگان
پایان
برگشت "ناشناخته: [" + رسانه + "]"
پایان
تابع ریشه:
سرچاپ توصیف("application/json")
سرچاپ توصیف("application/json; charset=utf-8")
سرچاپ توصیف("application/x-www-form-urlencoded")
سرچاپ توصیف("multipart/form-data; boundary=\"abc123\"")
سرچاپ توصیف("text/csv;charset=windows-1256")
سرچاپ توصیف("Application/JSON")
سرچاپ توصیف("")
پایانطبق استاندارد، نوع رسانه به بزرگی و کوچکی حرف حساس نیست، اما media_type همان شکلی را نگه میدارد که فرستاده شده است. media_type را پس از lower() مقایسه کنید، وگرنه کارخواهی که Application/JSON میفرستد به شاخهی ناشناخته میافتد.
ساختن و خواندن بارگذاری پرونده
فرم HTML که فیلد پرونده دارد multipart/form-data میفرستد: هر فیلد بخشی با سرآیندهای خودش میشود و بخشها با یک رشتهی مرزی از هم جدا میشوند. نویسنده چندبخشی جدید یکی را شروع میکند، نوشتن فیلد یک فیلد متنی میافزاید، نوشتن پرونده متنی و نوشتن پرونده یک پرونده، و بستن نویسنده بدنهی کامل را برمیگرداند. سرآیند نوع محتوا سرآیند متناظر را همراه با مرز میدهد. در سمت گیرنده، تجزیه چندبخشی بدنه و مرز را میگیرد و بخشها را برمیگرداند؛ بخشی که filename خالی ندارد یک پرونده است.
واردسازی شبکه.مایم
واردسازی فشرده سازی
تابع رسیدگی به بارگذاری(نوع: رشته، بدنه: فشرده سازی.بافر بایت):
نم := مایم.تجزیه نوع محتوا(نوع)
اگر نم.نوع رسانه != "multipart/form-data":
سرچاپ "۴۱۵ نوع رسانه پشتیبانی نمیشود"
برگشت
پایان
مرز := مایم.دریافت پارامتر(نم، "boundary")
بخشها := مایم.تجزیه چندبخشی(بدنه.داده، بدنه.طول، مرز)
هر ب در بخشها.اقلام:
اگر ب.نام پرونده.طول() > ۰:
سرچاپ "پرونده"، ب.نام، ب.نام پرونده، ب.نوع محتوا، ب.بدنه.طول، "بایت"
وگرنه:
سرچاپ "فیلد"، ب.نام، "="، فشرده سازی.بافر به رشته(ب.بدنه)
پایان
پایان
پایان
تابع ریشه:
ناپایا فرم := مایم.نویسنده چندبخشی جدید()
مایم.نوشتن فیلد(فرم، "title"، "سفر شیراز")
مایم.نوشتن فیلد(فرم، "album"، "۱۴۰۵")
مایم.نوشتن پرونده متنی(فرم، "notes"، "notes.txt"، ""، "روز اول: باغ ارم")
عکس := فشرده سازی.بافر از رشته("not really a jpeg")
مایم.نوشتن پرونده(فرم، "photo"، "eram.jpg"، ""، عکس.داده، عکس.طول)
بدنه := مایم.بستن نویسنده(فرم)
رسیدگی به بارگذاری(مایم.سرآیند نوع محتوا(فرم)، بدنه)
رسیدگی به بارگذاری("application/json"، بدنه)
پایاناگر برای بخش پرونده نوع محتوای خالی بدهید، نویسنده آن را از روی نام پرونده با رده مایم پر میکند؛ برای همین notes.txt و eram.jpg نوع گرفتهاند. بدنهای را که multipart/form-data نیست باید پیش از هر تجزیهای با وضعیت ۴۱۵ رد کرد.
یک نقطهی بارگذاری با net/http
همین دو نیمه روی یک اتصال واقعی هم کار میکنند. برنامهی زیر یک سرور اچ تی تی پی را روی 127.0.0.1 با یک مسیریاب راه میاندازد، فرمی با یک پروندهی متنی به آن میفرستد و آنچه رسیدگیکننده پیدا کرده را چاپ میکند. در رسیدگیکننده، Content-Type درخواست از سرآیند زمینه و بدنهی خام از بدنهی زمینه به دست میآید.
واردسازی شبکه.اچ تی تی پی
واردسازی شبکه.مسیریاب
واردسازی شبکه.مایم
واردسازی فشرده سازی
تابع بارگذاری(زمینه: صحیح۶۴):
نم := مایم.تجزیه نوع محتوا(اچ تی تی پی.سرصفحه(زمینه، "Content-Type"))
بدنه := اچ تی تی پی.بدنه(زمینه)
بخشها := مایم.تجزیه چندبخشی(بدنه برگردان تهی*، بدنه.طول()، مایم.دریافت پارامتر(نم، "boundary"))
ناپایا پاسخ := ""
هر ب در بخشها.اقلام:
پاسخ += ب.نام + ": " + فشرده سازی.بافر به رشته(ب.بدنه) + "\n"
پایان
اچ تی تی پی.متن(زمینه، پاسخ)
پایان
تابع ریشه:
ناپایا م := مسیریاب.مسیریاب جدید()
مسیریاب.ارسال(م، "/upload"، بارگذاری)
ناپایا س := اچ تی تی پی.سرور جدید(۱۸۵۸۷)
اچ تی تی پی.تنظیم میزبان(س، "127.0.0.1")
اچ تی تی پی.استفاده(س، م)
اگر وارونه اچ تی تی پی.اجرا در پس زمینه(س):
سرچاپ "درگاه ۱۸۵۸۷ گرفته است"
برگشت ۱
پایان
ناپایا فرم := مایم.نویسنده چندبخشی جدید()
مایم.نوشتن فیلد(فرم، "user"، "مریم")
مایم.نوشتن پرونده متنی(فرم، "todo"، "todo.txt"، "text/plain"، "خرید نان")
بدنه := مایم.بستن نویسنده(فرم)
سرصفحهها := نگاشت {} برگردان نگاشت<رشته، رشته>
سرصفحهها.درج("Content-Type"، مایم.سرآیند نوع محتوا(فرم))
جواب := اچ تی تی پی.ارسال با("http://127.0.0.1:18587/upload"، فشرده سازی.بافر به رشته(بدنه)، سرصفحهها)
سرچاپ جواب.وضعیت
چاپ جواب.بدنه
برگشت ۰
پایاندو محدودیت را بدانید. بدنهی زمینه یک رشته است و رشته در نخستین بایت صفر تمام میشود، پس پروندههای دودویی مثل تصویر از این راه بریده میرسند؛ بارگذاری متن مشکلی ندارد. و تجزیه چندبخشی سرآیندهای بخش، مثل Content-Disposition، را با همان بزرگی و کوچکی دقیق حرفها میجوید، که همان چیزی است که مرورگرها و نویسندهی همین بسته میفرستند.
گونهها
پارامتر نوع محتوا ContentTypeParam
ساختار پارامتر نوع محتوا| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| کلید | key | رشته = "" | نام، با همان بزرگی و کوچکی حروفی که فرستاده شده. |
| مقدار | value | رشته = "" | مقدار. |
واردسازی شبکه.مایم
تابع ریشه:
سرچاپ مایم.پسوند مایم("png")، مایم.پسوند مایم("json")، مایم.پسوند مایم(".png")
سرچاپ مایم.رده مایم("/site/index.html")، مایم.رده مایم("style.css")
سرچاپ مایم.متن وضعیت(۲۰۰)، مایم.متن وضعیت(۴۰۴)، مایم.متن وضعیت(۵۰۳)
ن := مایم.تجزیه نوع محتوا("text/html; charset=UTF-8; q=0.9")
سرچاپ ن.نوع رسانه، ن.پارامترها.اقلام.طول()، مایم.دریافت پارامتر(ن، "charset")، ن.پارامترها.اقلام[۱].کلید، ن.پارامترها.اقلام[۱].مقدار
پایانپارامترهای نوع محتوا ContentTypeParams
ساختار پارامترهای نوع محتوا| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| اقلام | items | وکتور<پارامتر نوع محتوا> | پارامترها. |
نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Types.salam
نوع محتوا ContentType
ساختار نوع محتواContent-Type تجزیهشده.| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| نوع رسانه | media_type | رشته = "" | نوع رسانه، بی فاصلههای دو طرف ولی با همان بزرگی و کوچکی حروفی که فرستاده شده. |
| پارامترها | params | پارامترهای نوع محتوا | پارامترها، مثل charset. |
نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Types.salam
سرآیند بخش MultipartHeader
ساختار سرآیند بخش| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| کلید | key | رشته = "" | نام. |
| مقدار | value | رشته = "" | مقدار. |
واردسازی شبکه.مایم
واردسازی فشرده سازی
واردسازی رشته
تابع ریشه:
ناپایا ن := مایم.نویسنده چندبخشی جدید()
سرچاپ رشته.شروع با(مایم.سرآیند نوع محتوا(ن)، "multipart/form-data; boundary=")
مایم.نوشتن فیلد(ن، "name"، "مریم")
مایم.نوشتن پرونده متنی(ن، "note"، "note.txt"، "text/plain"، "سلام")
داده := فشرده سازی.بافر از رشته("PNG")
مایم.نوشتن پرونده(ن، "pic"، "a.png"، "image/png"، داده.داده، داده.طول)
بدنه := مایم.بستن نویسنده(ن)
سرچاپ ن.بسته، بدنه.طول > ۰
ناپایا بخشها := مایم.تجزیه چندبخشی(بدنه.داده، بدنه.طول، ن.مرز)
هر ب در بخشها.اقلام:
سرچاپ ب.نام، "[" + ب.نام پرونده + "]"، "[" + ب.نوع محتوا + "]"، فشرده سازی.بافر به رشته(ب.بدنه)، ب.سرآیندها.اقلام.طول()
پایان
سرچاپ بخشها.اقلام[۱].سرآیندها.اقلام[۰].کلید
سرچاپ مایم.اندیس بخش(بخشها، "note")، مایم.اندیس بخش(بخشها، "missing")
سرچاپ مایم.مقدار بخش(بخشها، "name")، "[" + مایم.مقدار بخش(بخشها، "missing") + "]"
مایم.آزادسازی چندبخشی(بخشها)
پایانسرآیندهای بخش MultipartHeaders
ساختار سرآیندهای بخش| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| اقلام | items | وکتور<سرآیند بخش> | سرآیندها. |
نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
بخش چندبخشی MultipartPart
ساختار بخش چندبخشی| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| نام | name | رشته = "" | نام فیلد فرم. |
| نام پرونده | filename | رشته = "" | نام پرونده، اگر بخش پرونده باشد. |
| نوع محتوا | content_type | رشته = "" | نوع محتوای بخش. |
| سرآیندها | headers | سرآیندهای بخش | همهی سرآیندهای بخش. |
| بدنه | body | compress.ByteBuf | محتوای بخش. |
نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
بخشهای چندبخشی MultipartParts
ساختار بخشهای چندبخشی| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| اقلام | items | وکتور<بخش چندبخشی> | بخشها. |
نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
نویسنده چندبخشی MultipartWriter
ساختار نویسنده چندبخشی| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| مرز | boundary | رشته = "" | مرز تصادفی میان بخشها. |
| بافر | buf | compress.ByteBuf | بدنهی ساختهشده. |
| بسته | closed | منطقی = نادرست | آیا بسته شده. |
نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
تابعها
پسوند مایم MimeExt
تابع پسوند مایم(ext: رشته): رشتهpng؛ برای پسوند ناشناخته application/octet-stream. حدود ۲۵ پسوند رایج وب شناخته میشوند.نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Types.salam
رده مایم MimeType
تابع رده مایم(p: رشته): رشتهapplication/octet-stream.نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Types.salam
متن وضعیت StatusText
تابع متن وضعیت(code: صحیح): رشتهNot Found برای ۴۰۴.نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Types.salam
تجزیه نوع محتوا ParseContentType
تابع تجزیه نوع محتوا(header: رشته): نوع محتواContent-Type را تجزیه میکند.نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Types.salam
دریافت پارامتر ParamGet
تابع دریافت پارامتر(ct: نوع محتوا، key: رشته): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Types.salam
تجزیه چندبخشی ParseMultipart
تابع تجزیه چندبخشی(data: تهی*، n: صحیح، boundary: رشته): بخشهای چندبخشیmultipart/form-data را در حافظه با مرز دادهشده به بخشها تقسیم میکند؛ برای گرفتن پروندههای بارگذاریشده. بدنههای دودویی در بافر بایت هر بخش کامل میمانند.نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
اندیس بخش PartIndex
تابع اندیس بخش(parts: بخشهای چندبخشی، name: رشته): صحیحparts.items؛ اگر چنین بخشی نباشد -1.نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
مقدار بخش PartValue
تابع مقدار بخش(parts: بخشهای چندبخشی، name: رشته): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
آزادسازی چندبخشی FreeMultipart
تابع آزادسازی چندبخشی(parts &: بخشهای چندبخشی)تجزیه چندبخشی داده، آن را صدا بزنید.نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
نویسنده چندبخشی جدید NewMultipartWriter
تابع نویسنده چندبخشی جدید(): نویسنده چندبخشینمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
سرآیند نوع محتوا ContentTypeHeader
تابع سرآیند نوع محتوا(w: نویسنده چندبخشی): رشتهContent-Type که باید با این بدنه فرستاده شود.نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
نوشتن فیلد WriteField
تابع نوشتن فیلد(w &: نویسنده چندبخشی، name: رشته، value: رشته)نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
نوشتن پرونده WriteFileBytes
تابع نوشتن پرونده(w &: نویسنده چندبخشی، name: رشته، filename: رشته، content_type: رشته، data: تهی*، n: صحیح)نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
نوشتن پرونده متنی WriteFileStr
تابع نوشتن پرونده متنی(w &: نویسنده چندبخشی، name: رشته، filename: رشته، content_type: رشته، data: رشته)نمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam
بستن نویسنده CloseWriter
تابع بستن نویسنده(w &: نویسنده چندبخشی): compress.ByteBufنمونهی این مورد همراه با موارد بالاتر آمده است: net-mime-Multipart.salam