用户发表一篇文章,插入图片之前先上传图片到了服务器,但他并未发布就把网页关掉了,怎么处理? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
vvniu
V2EX    程序员

用户发表一篇文章,插入图片之前先上传图片到了服务器,但他并未发布就把网页关掉了,怎么处理?

  •  
  •   vvniu 2014-04-26 19:17:03 +08:00 8514 次点击
    这是一个创建于 4193 天前的主题,其中的信息可能已经有所发展或是发生改变。
    目前的思路是每上传一张图片就在数据库里建立一个一数据,加一个字段0,当发表时正则过滤所有文章里的图片然后改写数据库里相应图片的字段为1,然后在夜深人静没人上网的时候刷新一遍数据库把所有字段为0的都给清空了。但是自己觉得是一个好不靠谱的方法啊。。。。any idea?
    36 条回复    2014-04-29 21:42:29 +08:00
    cevincheung
        1
    cevincheung  
       2014-04-26 19:18:49 +08:00
    discuz是这么干的:

    在你下次发帖的时候,提示有未使用的附件,要求你处理并且必须处理。否则无法发帖。如果本次还是没使用,ok,下次还接着提示。
    jsonline
        2
    jsonline  
       2014-04-26 19:47:15 +08:00 via Android
    最好不清空
    bearcat001
        3
    bearcat001  
       2014-04-26 19:53:25 +08:00
    看看这种思路行不?

    上传后的图片在tmp目录中,确定文章提交了才把它移动到可用的位置,否则等系统自动清空
    如果想要图片上传后预览,也可以弄一个链接地址用来显示图片,后端将其转换到临时目录中
    ericls
        4
    ericls  
       2014-04-26 19:56:38 +08:00 via Android
    楼主问出了困扰我多时的问题。。 谢谢楼主和楼上各位
    leafgray
        5
    leafgray  
       2014-04-26 19:57:15 +08:00
    上传临时目录,保存时再移动到正式使用的目录。定时清临时目录。
    ====
    或者插入时都先不上传,保存时再上传----这个没有FileApi的话,可能就得控件了。。

    一楼方法好像挺靠谱的。
    imganquan
        6
    imganquan  
       2014-04-26 19:59:16 +08:00 via iPhone
    我这里也是先进入tmp目录,再移动到业务数据目录。
    yakczh
        7
    yakczh  
       2014-04-26 20:17:47 +08:00
    把图片删了就没事了
    julyclyde
        8
    julyclyde  
       2014-04-26 20:51:20 +08:00
    weibo.COM解决这个问题的方案是:上传到图床,那是由另一个部门管理的

    另外weibo.COM的发言条目删除后,其附件图不删除
    vvniu
        9
    vvniu  
    OP
       2014-04-26 21:39:46 +08:00
    @cevincheung 好办法,但是不怎么人性化,但是又感觉最有效
    @bearcat001 @leafgray @imganquan 原来我也是这么想的,其实和我的设想大概都一个意思,但是要是一直都有人在发贴,怎么定时清理?然后在给图片加个时间字段?我觉得结合一楼的办法最好
    @ericls 有什么问题大家分享呗
    @julyclyde 那越堆越多咋办
    raincious
        10
    raincious  
       2014-04-26 21:48:21 +08:00
    (对高质量的网站来说)用户上传的任何东西都是有价值的,所以留着也无所谓。我个人是留着的(有一定怕麻烦的成分)

    就楼主的要求来说,附件不应该在发帖前上传才是,可以利用FLASH或者HTML5(不知道可不可以)先显示一个缩略图,用户发布内容的时候,服务器一并处理附件。
    ksc010
        11
    ksc010  
       2014-04-26 22:12:05 +08:00
    可能楼主觉得这样浪费存储空间什么的
    我觉得这种情况下
    可以不用管他上传了图片有没有使用
    只要保证不重复上传就ok了 (存储时候每个资源的唯一性)
    lincanbin
        12
    lincanbin  
       2014-04-26 22:15:31 +08:00 via Android
    上传时即将附件信息存进数据库,定时清理路径未在任何帖子中出现过的附件
    另外附件数据表还要保存filesize和md5
    防止重复上传
    julyclyde
        13
    julyclyde  
       2014-04-26 22:33:08 +08:00
    @vvniu 越堆越多那也是别的部门的事啊,weibo公司就是这么想滴。嘿嘿嘿……
    gfreezy
        14
    gfreezy  
       2014-04-26 23:09:18 +08:00   1
    就这么丢着好了,实际环境中这种无效的图片比例很小。删除图片获得的好处(一点点的硬盘空间)远远比不上给系统增加的复杂性。
    odirus
        15
    odirus  
       2014-04-26 23:38:40 +08:00
    用户上传的数据很珍贵,应当重视。用户上传图片后服务器端“顺便”记录文件的MD5值,记录到缓存中,下次上传图片的时候再“顺便”计算一下MD5,如果发现命中缓存,说明文件已经存在,并检索出文件名。有些情况下特别有用,比如很多公司还没有自己的图床,也许会使用第三方的存储,针对热门的文件(比如豆瓣东西,会有很多重复的图片),可以减少很大的压力。
    vvniu
        16
    vvniu  
    OP
       2014-04-26 23:44:58 +08:00
    @raincious 用的是所见即得的编辑器,所以得之前就上传,不上传做缩略图感觉更麻烦

    @gfreezy @ksc010 确实如此,但是清了心里书胡也算是好处吧~

    @lincanbin 防止重复上传我倒觉得没什么意义,只要不用就清空就是了
    vvniu
        17
    vvniu  
    OP
       2014-04-26 23:48:39 +08:00
    @odirus @raincious 但是每次要用md5查找一遍所有的文件的md5开销很大吧,相比之下还是浪费些储存空间来得好
    raincious
        18
    raincious  
       2014-04-26 23:49:21 +08:00
    @vvniu HTML5或者Flash就没什么问题。但是你得考虑自己写个WYSIWYG编辑器了。
    raincious
        19
    raincious  
       2014-04-26 23:56:20 +08:00
    @vvniu 我的方式是将某一段时间内的文件用一个文件名存在FTP的同一个目录下(是的,用户将文件上传到应用程序服务器之后,服务器会将它处理好之后传到FTP上),比如这周上传的文件,这周内就不能传第二个一样的了(FTP操作的时候会跳过重复的文件)。

    另外你可以实现一个统一的操作类来进行附件上传管理,比如每当用户上传一个文件之后,就将文件算好MD5,然后加到数据库中,如果之后又有一个一样的文件进来,直接拷贝数据库中的row然后改掉PK和上传者存回去就好了;而如果这是第一个出现在网站中的文件,就执行储存操作。

    另外个人觉得,如果你的网站是公共形式的,没有私密的内容(比如个人隐私相册),没必要区分用户的附件空间。就像V2EX一样,你发表的所有内容都不属于你了。
    vvniu
        20
    vvniu  
    OP
       2014-04-26 23:56:33 +08:00
    @raincious 就是因为写不出来。。。所以只能按照现有的来做,而目前只找到先上传的方法
    vvniu
        21
    vvniu  
    OP
       2014-04-27 00:00:02 +08:00
    @raincious 这样倒是确实可行,试试看
    odirus
        22
    odirus  
       2014-04-27 00:05:27 +08:00
    @vvniu 查找一遍所有的文件md5可以采用缓存的方法,redis里面时间复杂度为常数,不过一个大的系统每次都要在全局范围内查找的话,最终整个缓存会无比庞大,甚至不可控,这个时候可以参考关系数据库中的分库思路,按照图片类型、时间段等进行分别缓存,保存在不同的缓存服务器上。运算量最大的地方就是服务器计算文件的MD5值。不过很多时候都可以在WEB前端计算,上传图片之前先查询该文件是否已经被上传过了,我想会好一些。
    raincious
        23
    raincious  
       2014-04-27 00:07:08 +08:00
    @vvniu 嗯……我可能没说清楚,我的意思是,将文件算好MD5之后的文件名放在按照时间周期算出的目录下。不是将时间作为文件名。刚着急上床所以打错了,特此更正下。
    yueyoum
        24
    yueyoum  
       2014-04-27 00:27:41 +08:00
    以前我的处理方式是:

    简化一下


    附件表
    topic_attachment

    +------+---------+--------------+-----------+
    | id | name | upload_date | topic_id |
    +------+---------+--------------+-----------+


    上传图片会先存入 topic_attachment 表,

    insert into topic_attachment (topic_id) values (0)
    注意这里把 topic_id 设置为0

    当帖子发布成功后,就把 topic_id 设置为当前发表的帖子ID。





    如果 上传完附件 ,但是帖子没发表。
    当下次打开网页的时候,
    就把 select * from topic_attachment where topic_id = 0;的结果返回
    并提示 这些附件 需要处理,如果不处理,多少天之后会删除。


    用户如果顺着提示点进去,再发贴的时候,就可以勾选这些列出来的附件。
    发表完,就把那些勾选的 attachment topic_id 设置为当前发布帖子的ID。


    整个流程就是这样, 既方便了用户,也给予了明确提示(如果不处理,多少天要删除)。
    顺便也清理了服务器上的无用文件。






    如果现在让我重新设计,

    我会用redis。

    用户只要是在编辑帖子,Javascript 就不停的 ajax post 帖子的内容到 server。
    server 将这些内容塞进redis,当然post的文件还是存磁盘。

    如果用户编辑到一半,关闭了浏览器,再打开帖子i编辑器的时候,
    Javascript会向server 查询是否有帖子缓存在redis中,如果有,server会返回帖子内容,
    Javascript自动填充, 这样就有了自动保存的功能。

    当用户点击了发表按钮后,POST到server,server再去存mysql,清理redis。

    如果用户编辑到一半,然后在也不打开帖子编辑了怎么办?
    用定时任务来处理,比如对于已经缓存了1周的帖子,就清除,连同它的附件。
    vvniu
        25
    vvniu  
    OP
       2014-04-27 00:54:37 +08:00
    @raincious 理解的
    @yueyoum 我的最终设计方式就是你这种,只不过不是过一定时间再删而是参考了一楼的方法,用户自动保存的功能我倒是觉得加一个放入草稿的按钮,让用户自己选择来得好点,要不很多时候保存一大堆没用的东西还得让用户自己删
    vvniu
        26
    vvniu  
    OP
       2014-04-27 00:57:41 +08:00
    @yueyoum 刚刚看了下redis,感觉还是有必要学的,有什么好的(经验/文章/网站)指导一下吗?ps:基本不会用数据库,只会最简单的几个语句
    xgod
        27
    xgod  
       2014-04-27 06:16:45 +08:00
    先存储到临时tmp目录,保存数据库时进行从临时目录移动到正式目录,没有什么性能问题,临时目录基本不用删除,撤消带附件的记录占实际业务比例很小的,而且硬盘很便宜的,基本不用纠结。
    ijse
        28
    ijse  
       2014-04-27 09:39:48 +08:00
    楼上们说的很受用~~ 多谢大家。

    我觉得保存用户正在编辑中的帖子,可以把内容保存在用户本地,比如用LocalStorage什么的,页面打开时检查本地存储的内容,如果有的话,可以提示恢复;这样用户在编辑时不必频繁与服务器通信。

    对于用户上传的文件,一般也会先保存在系统临时目录中,等用户保存后再移动到存档目录中。
    临时目录下的文件系统会自动清理,比如RHEL 默认会每30天清理一次旧文件,因此一般不必担心文件夹太大。

    用户在上传文件前先发一个请求比对下md5是不错的方法,可以只检查最近一段时间内重复的文件,这样也可以节省用户上传文件的等待时间。

    不过我还是习惯自己在确认文件没用的前提下自己清理。
    learnshare
        29
    learnshare  
       2014-04-27 11:15:39 +08:00
    shinebay
        30
    shinebay  
       2014-04-27 23:02:46 +08:00
    把它C盘格式化了
    lm902
        31
    lm902  
       2014-04-28 06:38:53 +08:00 via iPhone
    图片缓存到浏览器local storage,点击发布才上传
    dong3580
        32
    dong3580  
       2014-04-28 11:17:03 +08:00
    @ijse
    保存在用户本地不可靠,某一次我编辑v2ex的帖子,回复了很长。。。然后。。。然后谷歌浏览器突然崩溃了。。。
    leafgray
        33
    leafgray  
       2014-04-28 12:07:58 +08:00
    @vvniu
    上传的文件有时间可以区分。。。。

    定时删就是只删某个时间前的,在临时目录呆了三五天还没移到正式的应该可以认为是放弃了吧?
    ===
    不差存储的话,就用户空间,标识下用没用。
    sun019
        34
    sun019  
       2014-04-28 14:50:09 +08:00
    别走远了 discuz 的方法挺靠谱的 但是也要看用到什么场景了
    zstxt1989
        35
    zstxt1989  
       2014-04-29 09:35:21 +08:00
    还是先上传到临时目录,保存时移动到存储区吧。
    如果要建立附件归属关系,就得用dz的方法了。
    lygmqkl
        36
    lygmqkl  
       2014-04-29 21:42:29 +08:00
    大数据时代 分开做个单独的图床就行了。。。。 不要那么洁癖。。。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2559 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 02:14 PVG 10:14 LAX 19:14 JFK 22:14
    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