PHP如何实现即时的下载转发并且不卡内存?

2014-01-15 11:27:39 +08:00
 chsola
U-HACKS有一个加速下载uploaded.to网盘下载的造福服务:
http://u-hacks.net/accountboerse.php
这个是他们完全PHP实现的。
我有ryushare,rapidshare,bitshare,lumfile,freakshare的高级用户,
也想做一个这种加速下载的项目造福大众。
那几个网盘分享的文件没有高级账户完全拖不动,而且一般10$/m略贵。
目前下载过程难度不大,关键是发送。
在获取到一个请求加速的链接以后,我的服务器去拖文件,
怎么能做到边拖文件边发送给用户?
目前最大的问题就是我的下行不一定和用户的下行对等。
采用php+nginx发送在php清空缓冲以后输出到nginx,nginx关了gzip可以直接输出,但是还是会把发送过来的内容放到内存里面,造成内存的堆积。
有没有什么好办法用PHP实现边下边发?
p.s 我没多大的硬盘来做存储 ,只能转发, 为何纠结于PHP实现?我也不知道。
5580 次点击
所在节点    PHP
31 条回复
Archangel_SDY
2014-01-15 11:51:37 +08:00
又没硬盘又没内存又发不出去,那我觉得你只能下载的时候限速了。
chsola
2014-01-15 11:55:51 +08:00
@Archangel_SDY 并不是完全没有内存,我的小服内存只有16G,下载文件堆积多了爆内存内存再大内存也受不了.
下载到硬盘再发送让用户等太慢,我想做到像uhacks那种即时发送
Archangel_SDY
2014-01-15 12:05:04 +08:00
@chsola 那我觉得放内存里也没太大问题,弄个队列控制下任务数吧。
shiny
2014-01-15 12:09:14 +08:00
chsola
2014-01-15 13:04:50 +08:00
@shiny 关键是我需要实现即时的转发,就像http://u-hacks.net/accountboerse.php这个一样
那种方法无法实现即时的文件转发,需要先下载下来我再发送,我是给下载加速的所以也不需要做反盗链或者下载限制什么的,即时性能最重要。
shiny
2014-01-15 13:51:58 +08:00
@chsola proxy 就是不需要下载下来再转发的啊。看清楚我的回复好吗?
chsola
2014-01-15 14:03:54 +08:00
@shiny 主要是proxy比较难以实现
我需要从uploaded.to获取文件
serverfault上的是个下载认证配置吧...
读文件是本地的
我的文件是即时使用curl从远端获取
菊苣有转发一个文件的示范的话跪求
nginx的proxy模块无法设置cookie,所以不能用于下行。
做nginxmod的话工程量太大。
feuvan
2014-01-15 14:20:34 +08:00
@chsola 难道 nginx proxy 不能设置Cookie: xxxx header吗?
est
2014-01-15 14:54:41 +08:00
@feuvan @shiny 你们的想法都比较逆天啊。用户请求一个rapidshare -> 修改nginx配置添加cookie头 ->重启nginx -> 用户得到下载内容?

我来回复楼主把。用libcurl去下载rapidshare,读取2048字节,给用户返回2048字节。一直到读取完毕。
horsley
2014-01-15 15:10:17 +08:00
如果不是像curl下下来那样存储转发的话,我觉得可以用socket的方法,用一个固定大小的小的缓冲区循环read,同时直接输出,这样应该就能少占用内存,直接转发,坏处是断点续传多线程什么的都不支持了
feuvan
2014-01-15 15:52:48 +08:00
@est 哪里要重启了?我说的是 proxy_set_header
suriv520
2014-01-15 16:27:04 +08:00
硬盘也是缓存。缓存是一定得有的。
另外,PHP的模型不适合干这个,别用PHP折腾了……
dorentus
2014-01-15 17:03:22 +08:00
@feuvan 改 nginx 配置需要 restart/reload nginx 才能生效。

另外楼主说的这个和 nginx 完全没关系吧。想要改 header 或者设 cookie 完全可以在 PHP 里面做(不过这也和楼主的问题没关系)。
chsola
2014-01-15 19:55:53 +08:00
@est 我需要怎么知道用户接受完了...
@horsley 这种可行,断点续传再想办法,记得idm有个重新捕捉
@suriv520 某种原因不得不php python的话打一个tcp解决输出
或者开udp灌
est
2014-01-15 19:58:42 +08:00
@chsola @est 我需要怎么知道用户接受完了...

你从rapidshare读取的字节都返回给客户端就可以直接die()了吧。TCP协议保证用户能接收完,如果用户真没接收完这个也不是你能控制的。
ovear
2014-01-15 20:18:56 +08:00
- -目前找不到可以读取一部分内容的php api或lib,lz可以找一下,或者用上面所说的
然后每次用完buffer以后,手动的unset试试?
donwa
2014-01-15 22:33:53 +08:00
如果网盘支持断点续传。
php就可以先下载一部分,传给用户,再下载后续的块继续下载,继续传给用户。

5~6年前好像做过一个php文件来下载大文件的。。。好像是这样的。
chsola
2014-01-15 23:10:14 +08:00
@est 有没有什么方法让nginx发送分割了的文件?我现在在考虑用户提交链接,我去扒取两个2m的片段,开始发送,用户接受完成了一个1m的片段后我开始准备下一个1m片段 并且清理已经发送的1m
est
2014-01-15 23:24:16 +08:00
@chsola 你的意思是rapidshare本来就是2M一个2M一个的文件,也是多个URL,用户需要点一次就下载完毕,而不需要麻烦人工去挨个点击下载?

这个其实也好做。限制一个session一个下载任务即可。客户端每5秒检查一次是否可以继续下载另外一个文件。这个也兼容老浏览器。

如果你技术足够牛逼可以在服务器接受同时多个TCP连接,保持cwnd置空无数据,但是不要断掉,然后只给其中一个tcp连接返回数据,一个文件传输完毕就关闭tcp连接开始给第二个tcp连接写数据。。依次类推。

现代浏览器的话,可以模仿mega那种,完全用html5的API实现js可控的下载。甚至可以实现多文件顺序下载。不过前后台架构也比较复杂了。
chsola
2014-01-15 23:32:44 +08:00
@est 不是,rapid上可能是几g的超大单文件,我利用高级会员可以断点续传,用户下载到了,我再给准备文件,用户不下载或者距离这个点超过1m,我就不准备

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/97081

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX