文章目录
- 背景
- 遇到的问题:
- 1、当通过response header 获取content-length 的时候,千牛的url 没有返回 content-length
- 2、涉及到鉴权的私有文件url 获取不到真正的content-length
- 一、解决获取不到content-length问题
- 方法:通过python 的requests.head(url,headers)指定header 里的Accept-Encoding参数,来获取文件流真实的content-length
- 原因:请求参数 headers里不指定文件流的Accept-Encoding,当服务器有对文件做了压缩后返回时,content-length就有可能获取不到
- 实验对比:
- 总结:
- 二、解决获取不到真正的content-length问题
- 思路1:服务器去掉鉴权的部分,通过requests.head 来直接获取真实的content-length
- 思路2:通过curl 我们可以获取到文件的几个字节的方式来 间接获取这个文件流的字节大小
- 方法和实验
- 总结
背景
把同一份文件分别存放到了两个oss(可以理解为两个存储商),通过两个oss 返回的下载 url 获取 两个文件的content-length 和 content-type信息,对比是否一致
遇到的问题:
1、当通过response header 获取content-length 的时候,千牛的url 没有返回 content-length
2、涉及到鉴权的私有文件url 获取不到真正的content-length
通过curl -i url 是可以返回同一个文件 存在两个url 的content-length 的,那怎么通过python解决以上两个问题呢(方法不一定最好,欢迎拍砖!)
一、解决获取不到content-length问题
方法:通过python 的requests.head(url,headers)指定header 里的Accept-Encoding参数,来获取文件流真实的content-length
原因:请求参数 headers里不指定文件流的Accept-Encoding,当服务器有对文件做了压缩后返回时,content-length就有可能获取不到
参考了博文:https://blog.csdn/chouhuan1877/article/details/100808814 有说明获取不到content-length的原因
实验对比:
def head_getcontent(file,srcDownloadUrl,distDownloadUrl):
session = requests.session()
headers = {
"Accept-Encoding": "identity"
}
# 通过requests.head()填入不同的参数处理千牛的文件url
src_only_url = requests.head(url=srcDownloadUrl)
src_url_headers = requests.head(url=srcDownloadUrl, headers=headers)
src_url_headers_stream = requests.head(url=srcDownloadUrl, stream=True, headers=headers)
print("src_only_url headers= {}".format(src_only_url.headers))
print("src_url_headers headers= {}".format(src_url_headers.headers))
print("src_url_headers_stream headers= {}".format(src_url_headers_stream.headers))
print("src_only_url Content-Length= {}".format(src_only_url.headers['Content-Length']))
print("src_url_headers Content-Length= {}".format(src_url_headers.headers['Content-Length']))
print("src_url_headers_stream Content-Length= {}".format(src_url_headers_stream.headers['Content-Length']))
报错:
Traceback (most recent call last):
File "F:/directory/Learn/request_url/head_get.py", line 76, in <module>
print(head_getcontent(file,s,d))
File "F:/directory/Learn/request_url/head_get.py", line 48, in head_getcontent
print("src_only_url Content-Length= {}".format(src_only_url.headers['Content-Length']))
File "D:\Anaconda3\lib\site-packages\requests\structures.py", line 52, in __getitem__
return self._store[key.lower()][1]
KeyError: 'content-length'
Process finished with exit code 1
总结:
1)先了解一下Accept-Encoding:https://baike.baidu/item/Accept-Encoding/3239902?fr=aladdin,说明服务器对文件做压缩处理了,浏览器请求获取文件信息时需要header 指定Accept-Encoding,追加 headers 参数:“Accept-Encoding”: “identity” 后,就可以解决:KeyError: ‘content-length’ 的问题
2)python 的 requests.head(url,header) 可以获取到url 服务器返回的header信息(是不是所有的都能获取呢?这个就不一定了)
二、解决获取不到真正的content-length问题
问题:通过header 指定编码格式来获取带有鉴权信息的文件的content-length的时候,由于鉴权的存在,获取到的content-length 不是真实的 content-length
dis_url_headers = requests.head(url=distDownloadUrl, headers=headers)
结果:
说明:requests.head 获取不到具有鉴权信息的文件content-length(或者是需要什么参数来指定?欢迎指教~)
思路1:服务器去掉鉴权的部分,通过requests.head 来直接获取真实的content-length
这个是可行的,但是,很依赖去掉鉴权的操作,于是有了思路2
思路2:通过curl 我们可以获取到文件的几个字节的方式来 间接获取这个文件流的字节大小
HTTP1.1 协议(RFC2616)开始支持获取文件的部分内容。通过在 Header 里两个参数实现的,客户端发请求时对应的是 Range ,服务器端响应时对应的是 Content-Range。
方法和实验
那么通过python如何实现呢?
要在发出带 Range 的请求后,服务器才会在 Content-Range 头部返回当前接受的范围和文件总大小,那只能是发出一个 指定header里 range 参数的请求头的get 请求了
def head_getcontent(file,srcDownloadUrl,distDownloadUrl):
headers = {
"Accept-Encoding": "identity",
"Range": "bytes=0-1"
}
# 处理千牛的url
src_only_url = requests.head(url=srcDownloadUrl)
src_url_headers = requests.head(url=srcDownloadUrl, headers=headers)
src_url_headers_stream = requests.head(url=srcDownloadUrl, stream=True, headers=headers)
print("src_only_url headers= {}".format(src_only_url.headers))
print("src_url_headers headers= {}".format(src_url_headers.headers))
print("src_url_headers_stream headers= {}".format(src_url_headers_stream.headers))
# print("src_only_url Content-Length= {}".format(src_only_url.headers['Content-Length']))
print("src_url_headers Content-Length= {}".format(src_url_headers.headers['Content-Length']))
print("src_url_headers_stream Content-Length= {}".format(src_url_headers_stream.headers['Content-Length']))
print("src_url_headers_stream Content-Range= {}".format(src_url_headers_stream.headers['Content-Range']))
# 处理oss2 的url
print("____________head_____________")
dis_only_url = requests.head(url=distDownloadUrl)
dis_url_headers = requests.head(url=distDownloadUrl, headers=headers)
dis_url_headers_stream = requests.head(url=distDownloadUrl, stream=True, headers=headers)
print("dis_only_url headers= {}".format(dis_only_url.headers))
print("dis_url_headers headers= {}".format(dis_url_headers.headers))
print("dis_url_headers_stream headers= {}".format(dis_url_headers_stream.headers))
print("dis_only_url Content-Length= {}".format(dis_only_url.headers['Content-Length']))
print("dis_url_headers Content-Length= {}".format(dis_url_headers.headers['Content-Length']))
print("dis_url_headers_stream Content-Length= {}".format(dis_url_headers_stream.headers['Content-Length']))
print("________session____get_____________")
requests.DEFAULT_RETRIES = 5 # 增加重试连接次数
session = requests.session()
requests.keep_alive = False # 关闭多余连接
dis_only_geturl = session.get(url=distDownloadUrl)
dis_geturl_headers = session.get(url=distDownloadUrl, headers=headers)
dis_geturl_headers_stream = session.get(url=distDownloadUrl, stream=True, headers=headers)
print("dis_only_geturl headers= {}".format(dis_only_geturl.headers))
print("dis_geturl_headers headers= {}".format(dis_geturl_headers.headers))
print("dis_geturl_headers_stream headers= {}".format(dis_geturl_headers_stream.headers))
print("dis_only_geturl Content-Length= {}".format(dis_only_geturl.headers['Content-Length']))
print("dis_geturl_headers Content-Length= {}".format(dis_geturl_headers.headers['Content-Length']))
print("dis_geturl_headers_stream Content-Length= {}".format(dis_geturl_headers_stream.headers['Content-Length']))
print("dis_geturl_headers_stream Content-Range= {}".format(dis_geturl_headers_stream.headers['Content-Range']))
返回:
总结
既要获取到 oss1 的content-length 也要获取到 oss2 带有鉴权的url静态资源信息 只能通过get 指定header 的range 让服务器返回 content-range 来对比了
如果需要转载请注明出处
如果有说的不对的地方或 有更好的实现方式,欢迎拍砖🧐 和 赐教😊
更多推荐
通过python request库获取文件大小和文件类型(解决报错:KeyError: ‘content-length‘)
发布评论