问题总结

1.django用post传文件,如何接收和下载?

data= request.FILES.get('file')#接收到的数据类型是<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
# print(data,type(data)) #<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>

with open(r'C:\Users\33101\Desktop\12\新建1111.txt','wb') as p:#这样可以写进文件,不能直接p.write(chunks())
    for chunk in data.chunks():
        p.write(chunk)

#读取发送过来的文件,并用base64加密
a=request.FILES.get("file").read()
print("传过来的文件:",a)
b=base64.b64encode(a)
print('加密后的文件:',b)


#接收多个文件:
files=request.FILES.getlist('up_file')
print(files,type(files))
for i in files:
    print(i.read())#读文件,得到二进制
    # print('*******************')
    print(i.name)#获取文件名字
    i.size#获取文件大小的数字(单位是B)

注:如果要查看自己请求发出的所有信息就发送到http://httpbin.org/post,这个url能返回给你你刚才发送的所有请求中的信息。

 

2.阿里云oss上传/删除图片

#阿里云oss上传图片
import oss2,datetime
data = request.FILES.get('file')  # 获取post传过来的文件,得到<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
print(data.file)  #这个就是你传过来的文件内容

#一下四项都是在阿里云获取的
OSS_URL = ''
OSS_NAME = ''
ALI_KEY_ID =''
ALI_KEY = ''

OSS_URL_HTTPS = 'https://'+OSS_NAME+'.'+OSS_URL+'.com'
#拼接个路径,是存放在oss服务器上的位置,注意要带上文件名字
#特别注意:在windows环境拼接的路径和linux上的路径不同,要注意区别。
oss_path = os.path.join('ele_seal', 'test', datetime.datetime.now().strftime('%Y%m%d'),'wwdf.png')#如果在windows机器上就会拼接成windows识别的路径,放到服务器上就不好使了

# oss_path = 'ele_seal/test/20200904/110.png'#手动拼接一个适合linux服务器上的路径

# 上传文件
# auth = oss2.Auth(ALI_KEY_ID, ALI_KEY)
# bucket = oss2.Bucket(auth, OSS_URL, OSS_NAME)
# result = bucket.put_object(oss_path,data.file)#oss_path就是你文件存放在oss服务器的位置(包含文件名),data.file就是你post传过来的文件的内容(.file是固定用法)
# print(result.status)#如果返回200就证明上传成功

#访问上传的图片(固定写法)
OSS_URL_HTTPS +'/'+ oss_path

#删除已上传的文件
auth = oss2.Auth(ALI_KEY_ID, ALI_KEY)
bucket = oss2.Bucket(auth, OSS_URL, OSS_NAME)
result = bucket.delete_object('ele_seal/test/20200904/110.png')
print(result.status)#返回参数204就删除成功,如果一直卡着,那就证明找不到该文件

 

3.正匹配手机号码:

# 判断手机号码格式是否正确
    regular = '^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(166)|(17[2|8])|(18[0,5-9])|(19[8|9]))\d{8}$'
    regular_obj = re.compile(regular)
    check_phone = re.match(regular_obj, phone)

 

4.获取http请求头内容

用request.META获取的是个大字典,就是请求头所有内容,剩下的就用get取值

a=request.META.get("CONTENT_TYPE") #如果是固定的请求头就直接变成大写,所有的-都变成——就可以获取值了
b=request.META.get("HTTP_APPID")#如果是手动加的就必须以HTTP_开头,再加你写的键(全部大写,遇到-就变成_)即可
c=request.META.get("HTTP_TIME")
d=request.META.get("HTTP_SIGN")

 

 

 

5.AES加密

from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import time
#token加密信息
CRYPTO_KEY = 'A@G#X*NHA@G#X*No'#必须16位,这里是字符串
CRYPTO_OFFSET = b'qqqqqqqqqqqqqqpq'#必须16位,这里是二进制


class HeaderCrypto(object):
    '''
    token 信息的加密与解密
    '''

    def __init__(self, crypto_key, crypto_offset):
        '''
        :param crypto_key=加密需要的key
        :param crypto_offset=加密需要的偏移量
        crypto_model=crypto采用的加密模式
        '''
        self.crypto_key = crypto_key.encode('utf-8')
        self.crypto_offset = crypto_offset
        self.crypto_model = AES.MODE_CBC

    def add_to_16(self, cry_con):
        '''
        :param cry_con=需要加密的json字符串进行16位倍数处理
        :return: 16位倍数的字符串
        不足16位倍数的用0进行填充
        '''
        zero_num = 16 - (len(cry_con.encode('utf-8')) % 16) if len(cry_con.encode('utf-8')) % 16 else 0
        res_cry_con = cry_con + ('\0' * zero_num)
        return res_cry_con.encode('utf-8')

    def encrypt(self, cry_con):
        '''
        :param cry_con=需要加密的字符串信息
        :return: 加密后的字符串信息
        因为AES加密后的字符串不一定是ascii字符集的,输出保存可能存在问题,所以这里转为16进制字符串
        '''
        res_cry_con = self.add_to_16(cry_con)
        cryptos = AES.new(self.crypto_key, self.crypto_model, self.crypto_offset)
        cipher_text = cryptos.encrypt(res_cry_con)
        return b2a_hex(cipher_text)

    def decrypt(self, cry_con):
        '''
        :param cry_con=需要解密的字符串信息
        :return: 解密后的json字符串
        解密后,去掉补足的空格用strip() 去掉
        '''
        cryptos = AES.new(self.crypto_key, self.crypto_model, self.crypto_offset)
        plain_text = cryptos.decrypt(a2b_hex(cry_con))
        return bytes.decode(plain_text).rstrip('\0')


crypto_dict = {
    'req_server': 'self.req_server',
    'source_sign': 'self.source_sign',
    'unique_sign': 'self.unique_sign',
    'phonenum': 'phonenum',
    'user_id': 'user_id',
    'user_type': 0,
    'datetime': int(time.time()),
}
obj=HeaderCrypto(CRYPTO_KEY,CRYPTO_OFFSET)
a=obj.encrypt(str(crypto_dict))
print(a)#加密后的值
# c=b'722501109bdd032f0ff9b4090dce0ce028803780ce695910b927ef646c8e3329c07a6b6d589a3ad72c1bca451360fd8cb3cd9d84682bd85d9066d1fd56cca66a8a63a60c2e483a7ccac5018401683d220459dfd1bd9ad4a60a6ead38ff637f7765143aa7d732c0372a5cdb3e460726f00e51961d650a19b57bf1f495d0b13a5c0353746f10cca0531bd5ce73dba790a475c572c363eeaaede6d0564f69de1ef0a2ac858013ed4bd281084496a9b11401bb8a95700782a0139eb4de6d680eb3ed'
#
# d=obj.decrypt(c)#解密时传的参数是二进制还是字符串均可。
# print(d,type(d))#解密后的值,是字符串
# {'req_server': 'self.req_server', 'source_sign': 'self.source_sign', 'unique_sign': 'self.unique_sign', 'phonenum': 'phonenum', 'user_id': 'user_id', 'user_type': 0, 'datetime': 1599530672}

 

6.字符串与二进制互转

# 字符串转二进制
a='我是谁'

# 法一
# b=a.encode()
# print(b,type(b))
# b'\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81' <class 'bytes'>
# 法二
# c=bytes(a,'utf-8')#utf-8不可省略
# print(c,type(c))
# b'\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81' <class 'bytes'>


# 二进制转字符串
e=b'\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81'

# 法一
c=e.decode()
print(c,type(c))
# 我是谁 <class 'str'>
# 法二
f=str(e,'utf-8')#正确的写法,结果是 我是谁 <class 'str'>
# f=str(e) #错误的写法,结果是 b'\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81' <class 'str'>

print(f,type(f))

 

7.字符串转字典(eval和ast.literal_eval)

a='{"r":113}'
print(a,type(a))
b=eval(a)#用eval很危险
print(b,type(b))
# {"r": 113} <class 'dict'>

# eval()函数功能强大,但也很危险,若程序中有以下语句: s=input(‘please input:’) print (eval(s))
# 下面举几个被恶意用户使用的例子:
# 1、运行程序,如果用户恶意输入:
# eval(“import(‘os’).system(‘ls -l’)”)
# 2、运行程序,如果用户恶意输入:
# eval(“open(‘a.txt’).read()”)
# 如果,当前目录中恰好有一个文件,名为a.txt,则恶意用户变读取到了文件中的内容。
# 3、运行程序,如果用户恶意输入
# 如果,当前目录中恰好有一个文件,名为a.txt,则恶意用户删除了该文件。/q :指定静音状态。不提示您确认删除
# eval(“import(‘os’).system(‘rm -rf a.txt’)”)
# 解决方法
import ast
c=ast.literal_eval(a)
print(c,type(c))
# {"r": 113} <class 'dict'>

 

8.读图片给图片进行base64加密

import base64
with open(r'C:\Users\33101\Desktop\234.jpg','rb') as f:
    m = base64.b64encode(f.read())
    print(m)#加密后的结果

 

9.requests接收文件

import requests
req = requests.get("http://www.baidu.com/")   //发起GET请求
print(req.text)                               //打印响应内容

req.ok           // 检查返回码是不是 '200 OK',如果是则返回True,否则返回False
req.url          // 查看请求的URL,也就是'http://www.baidu.com/'
req.text         // 查看返回的响应内容,返回的是Unicode数据,一般用于返回文本数据
req.content      // 查看返回的响应内容,返回的是二进制数据,一般用于返回图片,文件等二进制数据
req.status_code  // 查看返回的HTTP状态码,如 200,404,502 等
req.reason       // 查看返回的HTTP状态码文本原因,如 'Not Found''OK' 等
req.cookies      // 查看返回的cookies信息
req.header       // 查看返回的头部信息


#带参数的get请求:
import requests

params = {
    "wd": "hello",
    "rsv_spt": 1
}

req = requests.get("http://www.baidu.com/", params=params)   //相当于 requests.get("http://www.baidu.com/s?wd=hello&rsv_spt=1")
print(req.text)


#伪造请求头信息,发起GET请求:

import requests

headers = {    //定义请求头信息,通常只定义 User-Agent,其他请求头信息可以通过 F12 界面查看,参考:https://www.cnblogs.com/pzk7788/p/10500101.html
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
}

req = requests.get("http://www.baidu.com/", headers=headers)
print(req.text)

 

10.二进制生成图片BytesIO

from PIL import Image
from io import BytesIO

i = Image.open(BytesIO(二进制内容))#二进制可以是读的图片或者是requests获取的网络图片
i.save(r'C:\Users\33101\Desktop\12\1222223.png')

#例:
from PIL import Image
from io import BytesIO
r=requests.get('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599671244609&di=101c0cc3ab7c6ceb6a7e39433a1f2e94&imgtype=0&src=http%3A%2F%2Fa2.att.hudong.com%2F36%2F48%2F19300001357258133412489354717.jpg')

i = Image.open(BytesIO(r.content))
i.save(r'C:\Users\33101\Desktop\12\2230000.png')

 

11.用requests模块上传一个或者多个文件

需要用python的MultipartEncoder模块

借鉴文档:https://requests.readthedocs.io/zh_CN/latest/user/quickstart.html#json

注意要用POST请求发送文件

 

#上传文件分两种,一种是本地文件读成二进制上传,另一种是直接给个url可以下载文件或者是直接在网页上查看的url。
from requests_toolbelt.multipart.encoder import MultipartEncoder
import requests


# 举例:没有相同的键时
# payload = {'key1': 'value1', 'key2': 'value2'}
# r = requests.post("http://httpbin.org/post", data=payload)
# print(r.text)
#你发送的请求是这样的:
# {
#    ...
#   "form": {
#     "key2": "value2",
#     "key1": "value1"
#   },
#   ...
# }

# 举例:有相同的键时
# payload = (('key1', 'value1'), ('key1', 'value2'))
# r = requests.post('http://httpbin.org/post', data=payload)
# print(r.text)
#你发送的请求是这样的:
# {
#   ...
#   "form": {
#     "key1": [
#       "value1",
#       "value2"
#     ]
#   },
#   ...
# }

# 上传文件代码:
#请求的url
url = 'http://httpbin.org/post'
#携带的参数
# MultipartEncoder里面的fields是固定参数不要变,fields里面装的就是post请求携带的表单form里面的键值对,如果键都不同,就把fields写成字典,
# 如果有相同的键,就把fields写成大元组,大元组里面每个小元组都有两个值,第一个原来字典的键,第二个就是原来字典的值,这样有相同的键也能传值了

# 当没有重复的键时:
multipart_encoder = MultipartEncoder(
    fields={
        "key1": 'value1',
        "key2": 'value2',
        "key3": 'value3',
        #下面doc_file和file_url是两种传文件的方式,二选一,而字段名称doc_file和file_url是服务器那边规定的键的名称
        'doc_file': ('12012.docx', open(r'C:\Users\33101\Desktop\合同二.docx', 'rb'), 'application/msword'),#传文件(以二进制形式传)
        #'12012.docx'表示文件名(带后缀),open(r'C:\Users\33101\Desktop\合同二.docx', 'rb')是读出的本地文件(二进制格式),
        # 'application/msword'是指明该文件的格式(具体指代需要参考MIME手册)
        # 注意:值里面不要出现数字(int,float等格式),如果有就换成字符串
        'file_url':'https://agxn.oss-cn-beijing.aliyuncs.com/original_files/1599609/18063609.docx?file_name=18063609.docx',#传url
        #规定:值是url+?+file_name=文件名.后缀(这个规定看服务器那边自己怎么接,你这边url传的时候就怎么传,这里只是举个例子)
    }
)
# 请求头
headers = {
    "Content-Type": multipart_encoder.content_type,
           "token": 'token1',
           "appid": 'asd',
           "time": '12342123'
    }
#如果写 "Content-Type":'multipart/form-data',发送会失败,
# 因为MultipartEncoder实例化对象点出
# 来的content_type是"Content-Type": "multipart/form-data; boundary=538863300a764a09b03121d6ed73ee7e", 的

r = requests.post(url, data=multipart_encoder,headers=headers)
print(r.text)#对http://httpbin.org/post网站发送请求能看见自己发送的请求信息


# 当有重复的键时(需要将fields整体改成元组格式,这里是传url):
multipart_encoder = MultipartEncoder(
        fields = (("key1", 'value1'), ("key2", 'value2'), ("key3", 'value3'), 
                  ('file_url','https://agxn.oss-cn-beijin683/ece0b_86163683.docx?file_name=ece8f05a_063683.docx'),
                ('file_url','https://agxn.oss-cn-beijin683/ece0b_1123445.docx?file_name=ece8f1123445.docx'),
                ('file_url','https://agxn.oss-cn-beijin683/ece0b_7832434534.docx?file_name=7832434534.docx') 
                  ))

#r.text返回的结果如下(一定要往'http://httpbin.org/post'这个url发请求,才能返回你发的请求内容)
{
"args": {}, 
"data": "", 
"files": {}, 
"form": {
"file_url": [
"https://agxn.oss-cn-beijin683/ece0b_86163683.docx?file_name=ece8f05a_063683.docx", #这里是你传的三个url,直接发过去,不用解析成二进制
"https://agxn.oss-cn-beijin683/ece0b_1123445.docx?file_name=ece8f1123445.docx", 
"https://agxn.oss-cn-beijin683/ece0b_7832434534.docx?file_name=7832434534.docx"
], 
"key1": "value1", 
"key2": "value2", 
"key3": "value3"
}, 
"headers": {
"Accept": "*/*", 
"Accept-Encoding": "gzip, deflate", 
"Appid": "asd", 
"Content-Length": "811", 
"Content-Type": "multipart/form-data; boundary=b10788d23abb4461b93f308eb8a37a2a", 
"Host": "httpbin.org", 
"Time": "12342123", 
"Token": "token1", 
"User-Agent": "python-requests/2.24.0", 
"X-Amzn-Trace-Id": "Root=1-5f59bec0-3609d3e014c21ecbce886f12"
}, 
"json": null, 
"origin": "124.65.120.250", 
"url": "http://httpbin.org/post"
}


# 当有重复的键时(需要将fields整体改成元组格式,这里是传文件的二进制):
multipart_encoder = MultipartEncoder(
        fields = (("key1", 'value1'), ("key2", 'value2'), ("key3", 'value3'),
                  ('doc_file', ('111.docx', open(r'C:\Users\33101\Desktop\合同二.docx', 'rb'), 'application/msword')),
                  ('doc_file', ('222.docx', open(r'C:\Users\33101\Desktop\合同一.docx', 'rb'), 'application/msword')),
                  ('doc_file', ('333.docx', open(r'C:\Users\33101\Desktop\合同三.docx', 'rb'), 'application/msword')),
                  )
                                    )
)
#r.text返回的结果如下(一定要往'http://httpbin.org/post'这个url发请求,才能返回你发的请求内容)

{
"args": {}, 
"data": "", 
"files": {
"doc_file": "data:application/msword;base64,UEsDBBQABgAIAAAAIQBKvAJlNWxQSwECLQAUAAYAAODIAAAAA"#这里会很长,是3个文档的所有二进制加到了一起,这里删减了
}, 
"form": {
"key1": "value1", 
"key2": "value2", 
"key3": "value3"
}, 
"headers": {
"Accept": "*/*", 
"Accept-Encoding": "gzip, deflate", 
"Appid": "asd", 
"Content-Length": "41971", 
"Content-Type": "multipart/form-data; boundary=7ce811908b004b56985fc17305928f89", 
"Host": "httpbin.org", 
"Time": "12342123", 
"Token": "token1", 
"User-Agent": "python-requests/2.24.0", 
"X-Amzn-Trace-Id": "Root=1-5f59bd37-f5abd7a0b50ef630460962f0"
}, 
"json": null, 
"origin": "124.65.120.254", 
"url": "http://httpbin.org/post"
}

 

12.如果独立在项目之外,从一个py文件要用orm访问数据库

#在运行代码最上面加上这三行即可
import
os,django os.environ.setdefault("DJANGO_SETTINGS_MODULE", "elec_seal.settings")# elec_seal是django的项目名称 django.setup()

#这样下面的orm运行就不会报错
from api import models
a=models.ElectronicSeal.objects.filter(userid='lele')
print(a)

 

13.将一个文件夹压缩成zip文件(shutil)

import shutil
shutil.make_archive( base_name=r'C:\Users\33101\Desktop\11111' ,format='zip', root_dir=r'C:\Users\33101\Desktop\123' )
#base_name是压缩包生成的路径(11111是生成的压缩包的名字,没后缀)
#format是生成的压缩包的文件后缀
#root_dir是你要压缩的文件夹(整个文件夹的内容都被压缩到压缩包中)

 

14.os删除文件,文件夹

import os
import shutil

os.remove(path)   #删除文件
os.removedirs(path)   #删除空文件夹

shutil.rmtree(path)    #递归删除文件夹

 

15.跨域问题

需要先安装模块:
pip3 install django-cors-headers

在settings.py文件中增加以下内容

INSTALLED_APPS = [
    ...
    'corsheaders'#新注册个app(要先安装django-cors-headers)
    ...
 ] 

MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware',#这个是新加的,一定要在下面这一行的上面
    'django.middleware.common.CommonMiddleware', # 这一行原来就有
    ...
)
#跨域增加忽略(以下内容全是新加的)
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = ('*')#这是白名单,如果有报错就就把这一行注掉

CORS_ALLOW_METHODS = ( #允许的请求方法
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)

CORS_ALLOW_HEADERS = (#允许的请求头,全部都写在下面,如果有请求头不在这里就会拦截请求,可以手动进行添加
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
    'token',   
)

 

16.Python压缩多个文件成zip

Python接收多个网络文件,将多个二进制文件写入一个zip文件中

from elec_seal import settings

url1='https://tester/api/document/original/1301810724183494656'#找三个可以获取到文件的url,
#图片其实也行(百度找三张图片的url放进来也行)
url2='https://test.erver/api/document/original/1301810724183494657' url3='https://test/' lst=[url1,url2,url3] headers = { # "Content-Type": settings.CONTENT_TYPE1, "appid": settings.APPID, #自己定义的请求头 # "sign": settings.SIGN, # "time": cur_time } import requests import zipfile zip1=zipfile.ZipFile('C:\\Users\\33101\\Desktop\\456\\wezipppp.zip','w') #第一个参数是你要生成的zip文件放到
                                #哪里(需要加上生成的zip文件名字和后缀),w是写入的意思
for key,u in enumerate(lst): a=requests.get(u,headers=headers)#发送get请求获取到文件,a.content是固定写法,
                        #获取到文件的二进制,直接把他写成文件其实就可以看见了
zip1.writestr(f'w{key}e.pdf',a.content,zipfile.ZIP_DEFLATED)#zip1是zipfile.ZipFile实例化的对
                        #象,writestr是固定方法,这里循环的是多个url,
                        #参数f''就是自己给放到zip压缩包中的每一个文件命名,循环一次命名一个,
                       #而a.content就是每个url获取到的文件的二进制,最后DEFAULT是固定写法。
zip1.close() #必须关闭对象,否则写不出来zip,他不保存,zip就出不来

 

17.linux部署Python代码,中文+英文路径报错

from urllib.parse import quote
import string

path='/wwe/合同.docx' #这样的路径在linux系统下(python3.5)运行报错
#报错UnicodeEncodeError: 'ascii' codec can't encode characters in position 8-20: ordinal not in range(128)

#解决方式
new_path = quote(path, safe=string.printable) #这样处理一下path,后面直接调用new_path 即可,不会影响windows下的Python代码

 

posted @ 2020-09-03 17:30  圣君灬七夜  阅读(612)  评论(0编辑  收藏  举报