用本地服务代替网络服务, 使得需要依赖网络运行的一款第三方应用能够脱机运行。
使用 RESTful 架构的 falcon 包实现了基本的网络请求响应,在依赖的资源文件完整的情况下,程序可以脱机运行。 但是遇到资源文件缺失,需要通过网络下载补足的情况就会报错。
本地文件请求:GET http://127.0.0.1:8686/Download/example.zip
文件远程真实地址:GET http://down.domain.com/Download/example.zip
用什么方法能在 python 程序接收到本地文件请求时,由 python重定向
连接到文件远程真实地址,并将响应数据原样发回给本地第三方应用。类似于本地应用通过代理
的方式取得了文件。
用关键词redirect
在 Github 搜索了一些 python 项目,没找到特别适用的。
希望大侠不吝赐教,万分感谢。
最终使用方案, 感谢 @ec0 大侠的不吝赐教
url ='http://down.domain.com/Download/中文文件名示例.zip'
#中文文件名编码问题,参见https://github.com/Pylons/waitress/issues/318
resp.downloadable_as = '中文文件名示例.zip'.encode("utf-8").decode("latin1")
#设置响应Headers: 'Content-Length', 'Content-Type'
resp.set_headers(dict(list(requests.head(url).headers.items())[:2]))
chunk = lambda u: (yield from requests.get(u,stream=True).iter_content(chunk_size=8192))
resp.stream = chunk(url)
1
lizenghui 2022-03-31 19:50:15 +08:00
nginx 可以啊。
|
2
lon91ong OP @lizenghui 有没有相近的应用实例呢? nginx 似乎时个网站后台框架吧? 只玩过 RESTful 类的简单的
|
4
cheng6563 2022-03-31 20:02:56 +08:00
你收到请求后直接改下地址然后 urllib.request 发请求出去就行了啊,把收到的数据直接返回或者临时存盘再返回都行。HTTP 文件下载有几个特殊 Header 表示文件名什么的,你响应的时候填上就行。
|
5
cheng6563 2022-03-31 20:04:49 +08:00 1
你先试试写一个提供文件下载接口,随便返回点数据就行。
再写一个用 urllib.request 下载远程文件的用例。 最后把两个方法整合下就行了。 |
6
Puteulanus 2022-03-31 20:17:38 +08:00
听起来像个 cache proxy ,squid transparent proxy 是不是就能做
|
7
xuxuxu123 2022-03-31 20:26:54 +08:00
如果远程文件的真实地址是确定的,那么 nginx 反向代理就可以了
|
8
ClericPy 2022-03-31 20:43:07 +08:00
这说的是 gost 么... https://github.com/ginuerzh/gost
或者用 Python 随手写个端口转发? https://github.com/ClericPy/ichrome/issues/84 如果我理解错了, 就当没看到我 |
11
lon91ong OP @cheng6563 遇到资源文件比较大的情况,四五十 M 的大小, 没法等下载完了再响应, 这种情况怎么处理呢?
|
12
lon91ong OP @Puteulanus 感谢提供关键词 squid, 找到个相关的项目, https://github.com/GlobalRadio/squid-redirect
简单看了看 readme, 似乎用得上, 明天再看看 |
13
mingl0280 2022-03-31 23:43:08 +08:00
……你就不会检查一下 file exist 然后不存在的文件自动下载了返回么?
|
14
Tink 2022-03-31 23:51:39 +08:00 via Android
很多办法,上面说的 nginx 反代可以,也可以在你的程序里判断本地文件是否存在,不存在就去下载
|
15
biubiuF 2022-04-01 00:40:54 +08:00
iptables redirect
|
16
ec0 2022-04-01 03:10:59 +08:00
试试这段代码
``` class ProxyResource: ____def file_generator(self, url): ________with requests.get(url, stream=True) as r: ____________for chunk in r.iter_content(chunk_size=8192): ________________yield chunk ____def on_get(self, req, resp): ________resp.downloadable_as = 'example.zip' ________resp.stream = self.file_generator('http://down.domain.com/Download/example.zip') ``` |
17
lon91ong OP @ec0 太感谢了! 感激涕零了要!!!
另外遇到一点小麻烦, 不知道时这个方法的问题, 还是我用的 WSGI 标准的 waitress 包的问题, 在转发时没有转发 headers 信息, 文件长度、编码等信息全都丢失了 需要用什么方法补救呢? |
18
enrolls 2022-04-01 11:26:17 +08:00
这个需求就跟在腾讯云买了同主机和 cos 一个道理,主机跟 cos 免流量通信,cos 直接下载需要流量。主机返回 cos 的 body 出去。headers 可以一并 yield ,之后自己组装
|
20
ec0 2022-04-01 12:01:27 +08:00
这样呢?
``` def on_get(self, req, resp): ____resp.downloadable_as = 'example.zip' ____r = requests.head('http://down.domain.com/Download/example.zip') ____resp.content_length = r.headers['content-length'] ____resp.content_type = r.headers['content-type'] ____resp.stream = self.file_generator('http://down.domain.com/Download/example.zip') ``` |
22
macrorules 2022-04-01 12:46:42 +08:00
iptables -A PREROUTING -t nat -i eth1 -d 127.0.0.1:8686 -j DNAT --to-destination ${down.domain.com 的地址}
|
23
lon91ong OP @macrorules 这个操作不是只能在路由器上搞吗??程序里面没听说过啊!
|
24
macrorules 2022-04-02 23:18:12 +08:00
@lon91ong 这是在本地(你的电脑,笔记本)上操作的
|
25
lon91ong OP @macrorules 应该还要加上 Linux 系统的限制吧, Windows 没有 iptables 命令
|
26
lon91ong OP 使用 lambda 替代了 genreat 函数:
``` url ='http://down.domain.com/Download/example.zip' resp.downloadable_as=labfile.encode("utf-8").decode("latin1") #编码问题,参见 https://github.com/Pylons/waitress/issues/318 r = requests.head(url) resp.content_length = r.headers['content-length'] resp.content_type = r.headers['content-type'] chunk = lambda u: (yield from requests.get(u,stream=True).iter_content(chunk_size=8192)) resp.stream = chunk(url) ``` |