V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chsola
V2EX  ›  PHP

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

  •  
  •   chsola · 2014-01-15 11:27:39 +08:00 · 5573 次点击
    这是一个创建于 3952 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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实现?我也不知道。
    第 1 条附言  ·  2018-12-18 17:17:30 +08:00
    现在我有 200T 左右的存储了,破项目 17 年初就有点盈利了,初期 scaleway 转发各种网盘去节约存储成本。
    现在无所谓了,二手硬盘二手服务器 R0 扔在 OVH/online 很快乐。
    31 条回复    2016-12-29 22:16:04 +08:00
    Archangel_SDY
        1
    Archangel_SDY  
       2014-01-15 11:51:37 +08:00
    又没硬盘又没内存又发不出去,那我觉得你只能下载的时候限速了。
    chsola
        2
    chsola  
    OP
       2014-01-15 11:55:51 +08:00   ❤️ 1
    @Archangel_SDY 并不是完全没有内存,我的小服内存只有16G,下载文件堆积多了爆内存内存再大内存也受不了.
    下载到硬盘再发送让用户等太慢,我想做到像uhacks那种即时发送
    Archangel_SDY
        3
    Archangel_SDY  
       2014-01-15 12:05:04 +08:00
    @chsola 那我觉得放内存里也没太大问题,弄个队列控制下任务数吧。
    shiny
        4
    shiny  
       2014-01-15 12:09:14 +08:00
    chsola
        5
    chsola  
    OP
       2014-01-15 13:04:50 +08:00   ❤️ 1
    @shiny 关键是我需要实现即时的转发,就像http://u-hacks.net/accountboerse.php这个一样
    那种方法无法实现即时的文件转发,需要先下载下来我再发送,我是给下载加速的所以也不需要做反盗链或者下载限制什么的,即时性能最重要。
    shiny
        6
    shiny  
       2014-01-15 13:51:58 +08:00
    @chsola proxy 就是不需要下载下来再转发的啊。看清楚我的回复好吗?
    chsola
        7
    chsola  
    OP
       2014-01-15 14:03:54 +08:00   ❤️ 1
    @shiny 主要是proxy比较难以实现
    我需要从uploaded.to获取文件
    serverfault上的是个下载认证配置吧...
    读文件是本地的
    我的文件是即时使用curl从远端获取
    菊苣有转发一个文件的示范的话跪求
    nginx的proxy模块无法设置cookie,所以不能用于下行。
    做nginxmod的话工程量太大。
    feuvan
        8
    feuvan  
       2014-01-15 14:20:34 +08:00
    @chsola 难道 nginx proxy 不能设置Cookie: xxxx header吗?
    est
        9
    est  
       2014-01-15 14:54:41 +08:00   ❤️ 1
    @feuvan @shiny 你们的想法都比较逆天啊。用户请求一个rapidshare -> 修改nginx配置添加cookie头 ->重启nginx -> 用户得到下载内容?

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

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

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

    5~6年前好像做过一个php文件来下载大文件的。。。好像是这样的。
    chsola
        18
    chsola  
    OP
       2014-01-15 23:10:14 +08:00 via iPhone   ❤️ 1
    @est 有没有什么方法让nginx发送分割了的文件?我现在在考虑用户提交链接,我去扒取两个2m的片段,开始发送,用户接受完成了一个1m的片段后我开始准备下一个1m片段 并且清理已经发送的1m
    est
        19
    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
        20
    chsola  
    OP
       2014-01-15 23:32:44 +08:00 via iPhone
    @est 不是,rapid上可能是几g的超大单文件,我利用高级会员可以断点续传,用户下载到了,我再给准备文件,用户不下载或者距离这个点超过1m,我就不准备
    est
        21
    est  
       2014-01-15 23:38:58 +08:00
    @chsola 距离这个点超过1m是什么意思?
    manhere
        22
    manhere  
       2014-01-15 23:42:36 +08:00
    @est 我感觉是1分钟的意思
    est
        23
    est  
       2014-01-15 23:51:42 +08:00
    @manhere @chsola 感觉略复杂了。php里面探测tcp是否idle 恐怕有点麻烦。况且是在nginx后面。不准确啊。
    chsola
        24
    chsola  
    OP
       2014-01-15 23:57:17 +08:00 via iPhone   ❤️ 1
    @est 那个1m是指文件大小...把大文件看为一坨1m包的连续
    est
        25
    est  
       2014-01-15 23:59:22 +08:00   ❤️ 1
    @chsola 感觉没说到同一个位面上 。。。。。。。。。。。。
    chsola
        26
    chsola  
    OP
       2014-01-16 00:52:08 +08:00 via iPhone   ❤️ 1
    @est 我的表达不好...
    donwa
        27
    donwa  
       2014-01-16 12:46:27 +08:00 via iPhone   ❤️ 1
    @est 说的是把一个大文件分成很多块。一块一块下载。断点续传就是这样的。定义偏移和大小。
    donwa
        28
    donwa  
       2014-01-16 12:50:03 +08:00 via iPhone   ❤️ 1
    @est 可以模仿mega那种,完全用html5的API实现js可控的下载。甚至可以实现多文件顺序下载。不过前后台架构也比较复杂了。

    对这个比较赶兴趣,有相关资料吗?
    est
        29
    est  
       2014-01-16 13:27:34 +08:00   ❤️ 1
    @donwa 断点续传需要客户端浏览器大手术。去看看html5 file blob api 吧。

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

    https://mega.co.nz/#blog_1
    chsola
        30
    chsola  
    OP
       2014-01-17 10:48:18 +08:00
    @est 我看了看实际上要是纠结php的话用php打个socket发送就可以了,发送过程是阻断式所以我知道用户确实接受完毕了文件的片段,断点续传用socket实现也是有可能的。
    http://www.cnblogs.com/funlake/archive/2012/04/06/2435241.html
    已经有打好的可以用了~
    lwd2136
        31
    lwd2136  
       2016-12-29 22:16:04 +08:00   ❤️ 1
    这个最后实现没?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2637 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 10:46 · PVG 18:46 · LAX 02:46 · JFK 05:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.