PHP如何实现即时的下载转发并且不卡内存? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
chsola
V2EX    PHP

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

  •  
  •   chsola Jan 15, 2014 6127 views
    This topic created in 4488 days ago, the information mentioned may be changed or developed.
    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实现?我也不知道。
    Supplement 1    Dec 18, 2018
    现在我有 200T 左右的存储了,破项目 17 年初就有点盈利了,初期 scaleway 转发各种网盘去节约存储成本。
    现在无所谓了,二手硬盘二手服务器 R0 扔在 OVH/online 很快乐。
    31 replies    2016-12-29 22:16:04 +08:00
    Archangel_SDY
        1
    Archangel_SDY  
       Jan 15, 2014
    又没硬盘又没内存又发不出去,那我觉得你只能下载的时候限速了。
    chsola
        2
    chsola  
    OP
       Jan 15, 2014   1
    @Archangel_SDY 并不是完全没有内存,我的小服内存只有16G,下载文件堆积多了爆内存内存再大内存也受不了.
    下载到硬盘再发送让用户等太慢,我想做到像uhacks那种即时发送
    Archangel_SDY
        3
    Archangel_SDY  
       Jan 15, 2014
    @chsola 那我觉得放内存里也没太大问题,弄个队列控制下任务数吧。
    shiny
        4
    shiny  
    PRO
       Jan 15, 2014
    chsola
        5
    chsola  
    OP
       Jan 15, 2014   1
    @shiny 关键是我需要实现即时的转发,就像http://u-hacks.net/accountboerse.php这个一样
    那种方法无法实现即时的文件转发,需要先下载下来我再发送,我是给下载加速的所以也不需要做反盗链或者下载限制什么的,即时性能最重要。
    shiny
        6
    shiny  
    PRO
       Jan 15, 2014
    @chsola proxy 就是不需要下载下来再转发的啊。看清楚我的回复好吗?
    chsola
        7
    chsola  
    OP
       Jan 15, 2014   1
    @shiny 主要是proxy比较难以实现
    我需要从uploaded.to获取文件
    serverfault上的是个下载认证配置吧...
    读文件是本地的
    我的文件是即时使用curl从远端获取
    菊苣有转发一个文件的示范的话跪求
    nginx的proxy模块无法设置cookie,所以不能用于下行。
    做nginxmod的话工程量太大。
    feuvan
        8
    feuvan  
       Jan 15, 2014
    @chsola 难道 nginx proxy 不能设置Cookie: xxxx header吗?
    est
        9
    est  
       Jan 15, 2014   1
    @feuvan @shiny 你们的想法都比较逆天啊。用户请求一个rapidshare -> 修改nginx配置添加cookie头 ->重启nginx -> 用户得到下载内容?

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

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

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

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

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

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

    现代浏览器的话,可以模仿mega那种,完全用html5的API实现js可控的下载。甚至可以实现多文件顺序下载。不过前后台架构也比较复杂了。
    chsola
        20
    chsola  
    OP
       Jan 15, 2014 via iPhone
    @est 不是,rapid上可能是几g的超大单文件,我利用高级会员可以断点续传,用户下载到了,我再给准备文件,用户不下载或者距离这个点超过1m,我就不准备
    est
        21
    est  
       Jan 15, 2014
    @chsola 距离这个点超过1m是什么意思?
    manhere
        22
    manhere  
       Jan 15, 2014
    @est 我感觉是1分钟的意思
    est
        23
    est  
       Jan 15, 2014
    @manhere @chsola 感觉略复杂了。php里面探测tcp是否idle 恐怕有点麻烦。况且是在nginx后面。不准确啊。
    chsola
        24
    chsola  
    OP
       Jan 15, 2014 via iPhone   1
    @est 那个1m是指文件大小...把大文件看为一坨1m包的连续
    est
        25
    est  
       Jan 15, 2014   1
    @chsola 感觉没说到同一个位面上 。。。。。。。。。。。。
    chsola
        26
    chsola  
    OP
       Jan 16, 2014 via iPhone   1
    @est 我的表达不好...
    donwa
        27
    donwa  
       Jan 16, 2014 via iPhone   1
    @est 说的是把一个大文件分成很多块。一块一块下载。断点续传就是这样的。定义偏移和大小。
    donwa
        28
    donwa  
       Jan 16, 2014 via iPhone   1
    @est 可以模仿mega那种,完全用html5的API实现js可控的下载。甚至可以实现多文件顺序下载。不过前后台架构也比较复杂了。

    对这个比较赶兴趣,有相关资料吗?
    est
        29
    est  
       Jan 16, 2014   1
    @donwa 断点续传需要客户端浏览器大手术。去看看html5 file blob api 吧。

    http://stackoverflow.com/a/20254988/41948

    https://mega.co.nz/#blog_1
    chsola
        30
    chsola  
    OP
       Jan 17, 2014
    @est 我看了看实际上要是纠结php的话用php打个socket发送就可以了,发送过程是阻断式所以我知道用户确实接受完毕了文件的片段,断点续传用socket实现也是有可能的。
    http://www.cnblogs.com/funlake/archive/2012/04/06/2435241.html
    已经有打好的可以用了~
    lwd2136
        31
    lwd2136  
       Dec 29, 2016   1
    这个最后实现没?
    About     Help     Advertise     Blog     API     FAQ     Solana     2564 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 54ms UTC 02:07 PVG 10:07 LAX 19:07 JFK 22:07
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86