視圖函數簡稱視圖,本質上是一個簡單的python函數,它接受web請求而且返回web響應;響應的內容能夠是HTML網頁、重定向、404錯誤、XML文檔或圖像等任何東西,可是,不管視圖自己是個什麼處理邏輯,最好都返回某種響應html
視圖函數的代碼寫在哪都無所謂,只要它在你的python目錄下面,可是一般咱們約定將視圖放置在項目或應用程序目錄中的名爲views.py的文件中。python
下面是一個返回當前日期和時間做爲HTML文檔的視圖:程序員
from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
讓咱們逐行分析一下上面的代碼:web
首先,從django.http模塊導入了HttpResponse類,以及python的datetime庫ajax
接着,咱們定義了current_datetime視圖函數django
每一個視圖函數都接收一個HttpRequest對象做爲第一位置參數,通常取名爲request,你能夠取別的名字,但這不符合潛規則,最好不要那麼作json
視圖函數的名稱沒有強制規則,但儘可能不要和python及django內置的各類名稱重名,而且儘可能精確地反映出它的功能,好比這裏的current_datetime跨域
該視圖返回一個HttpResponse對象,其中包含生成的HTML頁面。瀏覽器
在django中返回http錯誤代碼是很是簡單的;HttpResponse的許多子類對應着除了200(表明OK)之外的一些經常使用的http狀態碼。安全
爲了標識一個錯誤,能夠直接返回那些子類中的一個實例,而不是普通的HttpResponse,想下面這樣:
from django.http import HttpResponse, HttpResponseNotFound def my_view(request): # ... if foo: return HttpResponseNotFound('<h1>Page not found</h1>') else: return HttpResponse('<h1>Page was found</h1>')
django爲404錯誤提供了一個特化的子類HttpResponseNotFound;因爲一些狀態碼不太經常使用,因此不是每一個狀態碼都有一個特化的子類。
也能夠向HttpResponse的構造器傳遞HTTP狀態碼,來建立你想要的任何狀態碼的返回類,像下面這樣:
from django.http import HttpResponse def my_view(request): # ... # Return a "created" (201) response code. return HttpResponse(status=201)
關鍵是在返回中提供status=201參數,別的什麼303之類的錯誤均可以參照上面的例子。
class django.http.Http404
這是一個django內置的異常類,能夠在須要的地方彈出它,django會捕獲它,而且帶上HTTP404錯誤碼返回你當前APP的標準錯誤頁面或者自定義錯誤頁面,像下面這樣:
from django.http import Http404 from django.shortcuts import render from polls.models import Poll def detail(request, poll_id): try: p = Poll.objects.get(pk=poll_id) except Poll.DoesNotExist: raise Http404("Poll does not exist") return render(request, 'polls/detail.html', {'poll': p})
爲了在django返回404時顯示自定義的HTML,能夠建立要給名爲404.html的HTML模版,並將其放置在模版樹的頂層,當DEBUG設置爲False時,此模版將被自動使用,當DEBUG爲True時,能夠向Http404提供消息,它將顯示在標準的內置404調試模版中,可使用這些消息進行調試。
django在django.shortcuts模塊中,爲咱們提供了不少快捷方便的類和方法,它們都很重要,使用頻率很高。
(1)render()
render(request,template_name,context=None,content_type=None,status=None,using=None)
結合一個給定的模版和一個給定的上下文字典,返回一個渲染後的HttpResponse對象。
必須參數:
可選參數:
示例:
下面的示例將渲染模版myapp/index.html,MIME類型爲application/xhtml+xml:
from django.shortcuts import render def my_view(request): # View code here... return render(request, 'myapp/index.html', { 'foo': 'bar', }, content_type='application/xhtml+xml')
與下面的示例效果同樣:
from django.http import HttpResponse from django.template import loader def my_view(request): # View code here... t = loader.get_template('myapp/index.html') c = {'foo': 'bar'} return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')
(2)redirect()
redirect(to,permanent=False,args,*kwargs)
根據傳遞進來的URL參數,返回HttpResponseRedirect
參數to能夠是:
默認狀況下是臨時重定向,若是設置permanent=True將永久重定向。
示例:
調用對象的get_absolute_url()方法來重定向URL:
from django.shortcuts import redirect def my_view(request): ... object = MyModel.objects.get(...) return redirect(object)
傳遞視圖名,使用reverse()方法反向解析url:
def my_view(request): ... return redirect('some-view-name', foo='bar')
重定向到硬編碼的URL:
def my_view(request): ... return redirect('/some/url/')
也適用於完整的URL:
def my_view(request): ... return redirect('https://example.com/')
全部上述形式都接受permanent參數,若是設置爲true將返回永久重定向:
def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True)
(3)get_object_or_404()
get_object_or_404(klass,*args,**kwargs)
這個方法很是有用,經常使用於查詢模型對象,找到則進行下一步處理,若是未找到則給用戶返回404頁面
在後臺,django實際上是調用了模型管理器的get()方法,只是返回一個對象,不一樣的是,若是get()發生異常,會引起Http404異常,從而返回404頁面,而不是模型的DoesNotExist異常。
必需參數:
klass:要獲取的對象的model類名或者QuerySet等
**kwargs:查詢的參數,格式應該能夠被get()接受
示例:
從MyModel中使用主鍵1來獲取對象:
from django.shortcuts import get_object_or_404 def my_view(request): my_object = get_object_or_404(MyModel, pk=1)
上面的例子同下面同樣:
from django.http import Http404 def my_view(request): try: my_object = MyModel.objects.get(pk=1) except MyModel.DoesNotExist: raise Http404("No MyModel matches the given query.")
除了傳遞model名稱,還能夠傳遞一個QuerySet實例:
queryset = Book.objects.filter(title__startswith='M') get_object_or_404(queryset, pk=1)
上面的示例不夠簡潔,由於它等同於:
get_object_or_404(Book, title__startswith='M', pk=1)
可是若是你的queryset來自其餘地方,它就會頗有用了
還可使用manager,若是你自定義了管理器,這將頗有用:
get_object_or_404(Book.dahl_objects, title='Matilda')
還可使用related managers:
author = Author.objects.get(name='Roald Dahl') get_object_or_404(author.book_set, title='Matilda')
與get()同樣,若是找到多個對象將引起一個MultipleObjectsReturned異常。
(4)get_list_or_404()
get_list_or_404(klass,*args,**kwargs)
這其實就是get_object_or_404多值獲取版本;在後臺,返回一個給定模型管理器上的filer()的結果,並將結果映射爲一個列表,若是結果爲空則彈出Http404異常
必需參數:
klass:獲取該列表的一個model、manager或QuerySet實例
**kwargs:查詢的參數,格式應該能夠被filter()接受
示例:
下面的示例從mymodel中獲取全部發布出來的對象:
from django.shortcuts import get_list_or_404 def my_view(request): my_objects = get_list_or_404(MyModel, published=True)
上面的例子同下面同樣:
from django.http import Http404 def my_view(request): my_objects = list(MyModel.objects.filter(published=True)) if not my_objects: raise Http404("No MyModel matches the given query.")
每當一個用戶請求發送過來,django將http數據包中的相關內容,打包成爲一個HttpRequest對象,並傳遞給視圖函數做爲第一個位置參數,也就是reques,視圖函數負責返回一個HttpResponse對象
HttpRequest和HttpResponse對象定義在django.http模塊中
(1)屬性
HttpRequest對象的大部分屬性是隻讀的,除非特別註明
if request.method == 'GET': do_something() elif request.method == 'POST': do_something_else()
經過這個屬性來判斷請求的方法,而後根據請求的方法不一樣,在視圖中執行不一樣的代碼。
以上只是比較重要和經常使用的,還有不少未列出,從上面能夠看到,除CONTENT_LENGTH和CONTENT_TYPE以外,請求中的任何HTTP頭部鍵轉換爲META鍵時,都會將全部字母大寫並將鏈接符替換爲下劃線最後加上HTTP_前綴,因此,一個叫作X-Bender的頭部將轉換成META中的HTTP_X_BENDER鍵。
{'Content-Length': '', 'Content-Type': 'text/plain', 'Host': '127.0.0.1:8000', 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch, br', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Cookie': 'sessionid=rff2y86kaa57vpsihwgo5j72v11c4m0i; csrftoken=tPHBVfuGzw4lYSNuaWYEXvJa2oiXlCEZeStm9LSLNfxRKxRY0p6xvYnr0518LN0L'}
(2)可自定義的屬性
(3)由中間件設置的屬性
django的contrib應用中包含的一些中間件會在請求上設置屬性:
if request.user.is_authenticated: ... # Do something for logged-in users. else: ... # Do something for anonymous users.
(4)方法
根據HTTP_X_FORWARDED_HOST和HTTP_HOST頭部信息獲取請求的原始主機,若是這兩個頭部沒有提供相應的值,則使用SERVER_NAME和SERVER_PORT,如:127.0.0.1:8000
注:當主機位於多個代理的後面,get_host()方法將會失敗,解決辦法之一是使用中間件重寫代理的頭部,以下示例:
from django.utils.deprecation import MiddlewareMixin class MultipleProxyMiddleware(MiddlewareMixin): FORWARDED_FOR_FIELDS = [ 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED_HOST', 'HTTP_X_FORWARDED_SERVER', ] def process_request(self, request): """ Rewrites the proxy headers so that only the most recent proxy is used. """ for field in self.FORWARDED_FOR_FIELDS: if field in request.META: if ',' in request.META[field]: parts = request.META[field].split(',') request.META[field] = parts[-1].strip()
例如:"https://example.com/music/bands/the_beatles/?print=true"
注:不鼓勵在同一站點混合部署HTTP和HTTPS,若是須要將用戶重定向到HTTPS,最好使用Web服務器將全部HTTP流量重定向到HTTPS。
可選參數salt用來爲密碼加鹽,提升安全係數。 max_age參數用於檢查Cookie對應的時間戳是否超時。
>>> request.get_signed_cookie('name') 'Tony' >>> request.get_signed_cookie('name', salt='name-salt') 'Tony' # assuming cookie was set using the same salt >>> request.get_signed_cookie('nonexistent-cookie') ... KeyError: 'nonexistent-cookie' >>> request.get_signed_cookie('nonexistent-cookie', False) False >>> request.get_signed_cookie('cookie-that-was-tampered-with') ... BadSignature: ... >>> request.get_signed_cookie('name', max_age=60) ... SignatureExpired: Signature age 1677.3839159 > 60 seconds >>> request.get_signed_cookie('name', False, max_age=60) False
HttpRequest.is_secure():若是使用的是Https,則返回True,表示鏈接是安全的。
HttpRequest.is_ajax():若是請求是經過XMLHttpRequest生成的,則返回True;這個方法的做用就是判斷,當前請求是否經過ajax機制發送過來的。
HttpRequest.read(size=None)
HttpRequest.readline()
HttpRequest.readlines()
HttpRequest.xreadlines()
HttpRequest.iter()
上面的幾個方法都是從HttpRequest實例讀取文件數據的方法。
能夠將HttpRequest實例直接傳遞到XML解析器,例如ElementTree:
import xml.etree.ElementTree as ET for element in ET.iterparse(request): process(element)
在HttpRequest對象中,GET和POST屬性都是一個django.http.QueryDict的實例。也就是說你能夠按本文下面提供的方法操做request.POST和request.GET。
request.POST或request.GET的QueryDict都是不可變,只讀的。若是要修改它,須要使用QueryDict.copy()方法,獲取它的一個拷貝,而後在這個拷貝上進行修改操做。
(1)方法
QueryDict 實現了Python字典數據類型的全部標準方法,由於它是字典的子類。
不一樣之處在於下面:
QueryDict.init(query_string=None, mutable=False, encoding=None):QueryDict實例化方法。注意:QueryDict的鍵值是能夠重複的
>>> QueryDict('a=1&a=2&c=3') <QueryDict: {'a': ['1', '2'], 'c': ['3']}>
若是須要實例化能夠修改的對象,添加參數mutable=True
classmethod QueryDict.fromkeys(iterable, value='', mutable=False, encoding=None):
循環可迭代對象中的每一個元素做爲鍵值,並賦予一樣的值。
>>> QueryDict.fromkeys(['a', 'a', 'b'], value='val') <QueryDict: {'a': ['val', 'val'], 'b': ['val']}>
QueryDict.__getitem__():返回給定鍵的值,若是鍵具備多個值,則返回最後一個值
QueryDict.__setitem__(ke,value):將給定鍵設置爲value,只能在可變的QueryDict上調用
QueryDict.__contains__():判斷給定鍵是否存在
QueryDict.get(ke,default=None):同__getitem__()相同,只是多個了默認值返回
QueryDict.setdefault(key,default=None):它在__setitem__()內部使用
QueryDict.update(other_dict):用新的QueryDict或字典更新當前QueryDict,相似dict.update(),可是追加內容,而不是更新並替換它們,以下:
>>> q = QueryDict('a=1', mutable=True) >>> q.update({'a': '2'}) >>> q.getlist('a') ['1', '2'] >>> q['a'] # returns the last '2'
QueryDict.items():相似dict.items(),若是有重複項目,返回最近的一個:
>>> q = QueryDict('a=1&a=2&a=3') >>> list(q.items()) [('a', '3')]
QueryDict.values():相似dict.values(),可是隻返回最近的值,以下:
>>> q = QueryDict('a=1&a=2&a=3') >>> list(q.values()) ['3']
QueryDict.copy():使用copy.deepcopy()返回QueryDict對象的副本,此副本是可變的
QueryDict.getlist(key,defautl=None):返回鍵對應的值的列表,若是該鍵不存在而且爲提供默認值,則返回一個空列表
QueryDict.setlist(key,list_):爲list_設置給定的鍵
QueryDict.appendlist(key,item):將鍵追加到內部與鍵相關聯的列表中
QueryDict.setdefault(key,default=None):相似dict.setdefault(),爲某個鍵設置默認值
QueryDict.lists():相似items(),只是它將其中的每一個鍵的值做爲列表放在一塊兒,以下:
>>> q = QueryDict('a=1&a=2&a=3') >>> q.lists() [('a', ['1', '2', '3'])]
QueryDict.pop(key):返回給定鍵的值的列表,並從QueryDict中移除該值,如鍵不存在則引起異常
>>> q = QueryDict('a=1&a=2&a=3', mutable=True) >>> q.pop('a') ['1', '2', '3']
QueryDict.popitem():刪除QueryDict任意一個鍵,並返回二值元組,包含鍵和鍵的全部值的列表,在一個空的字典上調用時將引起KeyErro,以下:
>>> q = QueryDict('a=1&a=2&a=3', mutable=True) >>> q.popitem() ('a', ['1', '2', '3'])
QueryDict.dict():將QueryDict轉換爲python字典數據類型,並返回該字典,若是出現重複的鍵,則將全部的值打包成一個列表,改成新字典中鍵的值
>>> q = QueryDict('a=1&a=3&a=5') >>> q.dict() {'a': '5'}
QueryDict.urlencode(safe=Noen):爲已編碼的格式返回數據字符串:
>>> q = QueryDict('a=2&b=3&b=5') >>> q.urlencode() 'a=2&b=3&b=5'
使用該safe參數傳遞不須要編碼的字符:
>>> q = QueryDict(mutable=True) >>> q['next'] = '/a&b/' >>> q.urlencode(safe='/') 'next=/a%26b/'
HttpResponse類定義在django.http模塊中
HttpRequest對象由django自動建立,而HttpResponse對象則由程序員手動建立,咱們編寫的每一個視圖都要實例化、填充和返回一個HttpResponse對象,也就是函數的return值。
(1)使用方法
傳遞字符串:
最簡單的方式his傳遞一個字符串做爲頁面的內容到HttpResponse構造函數,並返回給用戶:
>>> from django.http import HttpResponse >>> response = HttpResponse("Here's the text of the Web page.") >>> response = HttpResponse("Text only, please.", content_type="text/plain") >>> response = HttpResponse(b'Bytestrings are also accepted.')
但,若是要增量添加內容,能夠將其response用做類文件對象,使用write()方法不斷往裏增長內容:
>>> response = HttpResponse() >>> response.write("<p>Here's the text of the Web page.</p>") >>> response.write("<p>Here's another paragraph.</p>")
傳遞可迭代對象:
HttpResponse會當即處理迭代器,並把它的內容存成字符串,最後廢棄這個迭代器,好比文件在讀取後,會馬上調用close()方法,關閉文件
設置頭部字段:
能夠把HttpResponse對象看成一個字典同樣,在其中增長和刪除頭部字段:
>>> response = HttpResponse() >>> response['Age'] = 120 >>> del response['Age']
注意!與字典不一樣的是,若是要刪除的頭部字段若是不存在,del不會拋出KeyError異常。
HTTP的頭部字段中不能包含換行。因此若是咱們提供的頭部字段值包含換行符(CR或者LF),將會拋出BadHeaderError異常
告訴瀏覽器將響應視爲文件附件:
讓瀏覽器以文件附件的形式處理響應,須要聲明content_type類型和設置Content-Disposition頭信息,給瀏覽器返回一個微軟電子表格:
>>> response = HttpResponse(my_data, content_type='application/vnd.ms-excel') >>> response['Content-Disposition'] = 'attachment; filename="foo.xls"'
(2)屬性
HttpResponse.content:響應的內容,bytes類型
HttpResponse.charset:編碼的字符集,若是沒指定,將會從content_type中解析出來
HttpResponse.status_code:響應的狀態碼,好比200
HttpResponse.reason_phrase:響應的HTTP緣由短語,使用標準緣由短語,除非明確設置,不然reason_phrase由status_code的值決定
HttpResponse.streaming:這個屬性的值老是False,因爲這個屬性的存在,使得中間件可以區別對待流式響應和常規響應
HttpResponse.closed:若是響應已關閉,那麼這個屬性的值爲True
(3)方法
HttpResponse.init(content='',content_type=None,status=200,reason=None,charset=None):響應的實例化方法,使用content參數和content_type實例化一個HttpResponse對象;content應該是一個迭代器或者字符串,若是是迭代器,這個迭代器返回的應是字符串,而且這些字符串鏈接起來造成response的內容,若是不是迭代器或者字符串,那麼在其被接收的時候將轉換成字符串。
content_type是可選的,用於填充HTTP的content_type頭部,若是未指定,默認狀況下由DEFAULT_CONTENT_TYPE和DEFAULT_CHARSET設置成:text/html;charset=utf-8
status是響應的狀態碼,resaon是HTTP響應短語,charset是編碼方式
HttpResponse.has_header(header):檢查頭部中是否有給定的名稱(不區分大小寫),返回true或false
HttpResponse.__setitem__(header,value):設置標頭
HttpResponse.__delitem__(header):刪除標頭
HttpResponse.__getitem__(header):查看標頭
HttpResponse.setdefault(header,value):設置一個頭部,除非該頭部已經設置過了
HttpResponse.set_cookie(key,value='',max_age=None,expires=None,path='/',domain=None,secure=None,httponly=False):設置一個cookie,參數與python標準庫中的Morsel.Cookie對象相同;max_age爲生存週期以秒爲單位;expires爲到期時間;domain用於設置跨域的cookie
若是你想阻止客戶端的JavaScript訪問cookie,能夠設置httponly=True
HttpResponse.set_signed_cookie(key,value,salt='',max_age=None,expires=None,path='/',domain=None,secure=None,httponly=True):與set_cookie相似,可是在設置以前將對cookie進行加密簽名,一般與HttpResponse.get_signed_cookie()一塊兒使用
HttpResponse.delete_cookie(key,path='/',domain=None):刪除cookie中指定的key,因爲cookie工做方式,path和domain應該與set_cookie()使用的值相同,不然cookie不會刪除
HttpResponse.write(content):將HttpResponse實例看做相似文件的對象,往裏添加內容
HttpResponse.flush():清空HttpResponse實例的內容
HttpResponse.tell():將HttpResponse實例看做相似文件的對象,移動位置指針
HttpResponse.getvalue():返回HttpResponse的值,此方法將HttpResponse實例看做是一個相似流的對象
HttpResponse.readable():此方法使HttpResponse實例成爲相似流的對象,值始終爲False
HttpResponse.seekable():此方法使HttpResponse實例成爲相似流的對象,值始終爲False
HttpResponse.writable():此方法使HttpResponse實例成爲相似流的對象,值始終爲True
HttpResponse.writelines(lines):將一個包含行的列表寫入響應對象中,不添加分行符
(4)HttpResponse子類
Django包含許多HttpResponse衍生類(子類),用來處理不一樣類型的HTTP響應,這些子類存在於django.http之中:
class HttpResponseRedirect:用來重定向,第一個參數必須是重定向到的路徑,能夠是徹底限定的URL,或沒有域的絕對路徑,或者是相對路徑;它將返回狀態碼302
class HttpResponsePermanentRedirect:永久重定向,返回301狀態碼
class HttpResponseNotModified:未修改頁面,返回304狀態碼
class HttpResponseBadRequest:錯誤的請求,返回400狀態碼
class HttpResponseNotFound:頁面不存在,返回404狀態碼
class HttpResponseForbidden:禁止訪問,返回403狀態碼
class HttpResponseNotAllowed:禁止訪問,返回405狀態碼
class HttpResponseGone:過時,返回410狀態碼
class HttpResponseServerError:服務器錯誤,返回500狀態碼
(5)JsonResponse類
classJsonResponse(data,encoder = DjangoJSONEncoder,safe = True,json_dumps_params = None,**kwargs)
JsonResponse是HttpResponse的一個子類,是Django提供的用於建立JSON編碼類型響應的快捷類
它從父類繼承大部分行爲,並具備如下不一樣點:
它的默認Content-Type頭部設置爲application/json
它的第一個參數data,一般應該爲一個字典數據類型,若是safe參數設置爲False,則能夠是任何可JSON序列化的對象
encoder默認爲django.core.serializers.json.DjangoJSONEncoder,用於序列化數據
布爾類型參數safe默認爲True,若是設置爲False,能夠傳遞任何對象進行序列化,不然只容許dict實例
典型的用法以下:
>>> from django.http import JsonResponse >>> response = JsonResponse({'foo': 'bar'}) >>> response.content b'{"foo": "bar"}'
如要序列非dict對象,必須設置safe參數爲False,若是不傳遞safe=False,將拋出一個TypeError
>>> response = JsonResponse([1, 2, 3], safe=False)
若是你須要使用不一樣的JSON編碼器類,能夠傳遞encoder參數給構造函數:
>>> response = JsonResponse(data, encoder=MyJSONEncoder)
(6)StreamingHttpResponse類
StreamingHttpResponse類被用來從Django響應一個流式對象到瀏覽器。若是生成的響應太長或者是佔用的內存較大,這麼作可能更有效率。 例如,它對於生成大型的CSV文件很是有用。
StreamingHttpResponse不是HttpResponse的衍生類(子類),由於它實現了徹底不一樣的應用程序接口。可是,除了幾個明顯不一樣的地方,二者幾乎徹底相同:
它將被賦予一個迭代器,產生字符串做爲內容
除非經過迭代響應對象自己,不然沒法訪問其內容,只有在將響應返回給客戶端時纔會發生這種狀況
它沒有content屬性,相反,它有一個streaming_content屬性
你不能使用類文件對象tell()或write()方法
(7)FileResponse類
class FileResponse(open_file,as_attachment = False,filename='',**kwargs)
文件類型響應,一般用於給瀏覽器返回一個文件附件,FileResponse是StreamingHttpResponse的衍生類,爲二進制文件專門作了優化
若是as_attachment=True,則要求瀏覽器將文件做爲下載提供給用戶
若是open_file沒有名稱或名稱open_file不合適,請使用filename參數提供自定義文件名
FileResponse接受任何具備二進制內容的類文件對象,以下以二進制模式打開文件:
>>> from django.http import FileResponse >>> response = FileResponse(open('myfile.png', 'rb'))
上面的文件將自動關閉,所以不要使用上下文管理器打開它
FileResponse.set_headers方法,在2.1中添加的新功能,它在初始化期間自動調用和設置不一樣的報頭(Content-Length,Content-Type和Content-Disposition),使用哪一種報頭取決於打開的文件。
-------------------------------------------------------------------------------------------------------------------