业精于勤,荒于嬉。

如何优雅的文件上传

前言:

  写给java入门的人,写给在职需要提高广度的人。

  你需要有如下知识:

    你要知道什么是数据流,浏览器到底都能干什么,java有哪些IO相关的操作类。servlet与运行服务器环境(tomcat,weblogic等)有什么关系。

  如果你没有上述知识点,没关系,尽量往下看,如果你知识为了工作需要。

  我会按照如下格式书写:

    他们的实现是根据什么实现的,依赖什么,如何操作,最后会描述如何建立以个完整的项目中共通的文件上传功能。


 

  我们的目标:

    (没有蛀牙?)对于任何一条数据,应该有一个对应文件的扩展字段,而不是一套业务一套文件上传,换言之,一个文件上传的功能,需要适用于项目中所有的文件上传,如图:  

    

 

   这是我们认为文件上传的一个简单的过程。

   第一步,我们要在页面上直接上传文件到服务器,原因是某些文件需要及时预览一下,又或者为了提高客户体验,有时候我们会在一个表单中添加附件上床,更多的做法是,当用户选择一个文件之后,旁边有一个上传按钮,点击上传按钮,开始出现进度条,当进度条完成之后,客户开始继续填写表单,然而对于web开发,实时显示上传进度是非常不简单的事情,比如你可能需要flash的帮助,然而H5的世界说,flash正在被人类抨击。so,你肯让最终显示的是一个等待界面而已,不管如何,我们应该让用户先看到文件上传的等待,而不是最终一并提交,并且上传,因为这个过程很有可能出现问题,比如网络错误,服务器BUG,用户误操作等.....

  因为有了预先上传这个过程,最后用户可能获取到这个文件在服务器上的数据ID,即可进行提交,甚至你可以让用户填写表单到一半的时候继续填写,不用再次上传附件。

  一个典型的demo,就是aliyun 的备案(好吧,你说是万网的我也无话可说),当你的扫描件上传之后,关掉页面,下次进来是不需要你再次上传的,因为这已经是属于你的资源。


 

  第二步,我们需要根据业务来控制数据在服务器的位置,以及其他属性,通常,我们会把文件第一次上传到服务器上的一个临时存储目录,原因如下:

      1.你不能直接确定这个文件需要用在什么地方,因为你的文件上传可能是公用的,申报需要,注册需要,甚至后台管理也需要,所以你要有一个临时目录,什么文件都方进去,等知道这个文件是干嘛的之后,再移动出去。就好比新兵蛋子跟后期筛选一样。

      2.你可能最终不需要用这个文件,他是个垃圾,他不过是一些傻逼浪荡的用户上传的垃圾附件,上传完了,就完了,根本没提交表单(别骂人家,你也干过。)

      3.如果你的上传是共用的,那么如果你一开始就把文件上传到目标文件夹下面,或者其他什么文件系统下面,会很麻烦。(不解释)


 

  第三步,你需要让用户操作这个文件了,通常,这个文件上传之后会返回客户端一个文件ID,最终用户只是提交了这样一个文件ID,并不是提交表单的时候同时上传附件。so,问题来了,万一上传的附件错了,重新上传怎么办?万一上传的附件。。。问题太多,我们写个FAQ

      FAQ:

    • 上传错了,又点上传,怎么办?  
      服务器在每一次接收上传的时候,至少要保存【业务标记】【操作用户】【文件状态】,如果在当前业务下,该用户已经拥有一个临时文件,那么应该删掉原本文件,上传新的文件,使用之前的附件ID返回客户端;如果没有,那么直接上传新附件,并且生成附件数据ID,返回给客户端。保证用户在一个业务下只有一个临时文件。这里说的业务通常是一个表单字段,甚至是一个字段中的一个节点,比如注册用户,需要身份证反正面上传,这个时候可能反正面的附件ID,在同一个字段,如“cid_ufile_id_json”,他可能是一个json格式的字段,用来存储用户上传的身份验证附件。

    • 上传后没有使用,直接关掉浏览器了?  
            首先这不是个事,因为通常我们的项目,都会监听session关闭事件(多嘴一句,并不是浏览器关掉就会session销毁,这需要浏览器想服务器发送通知的,如果直接断电,很有可能没有这个通知。)你需要在session关闭的时候去清理session给服务器带来的垃圾。就好像你家客人走了之后你要收拾卫生一样。(这跟你背着你老婆找野女人不一样!!!!)如果是断电呢,不能及时清理,或者服务器就会有垃圾,不管什么原因,服务器很有可能存在一些“你以为”清理掉的垃圾,OK,做个corn定时清理下吧,这就是为什么刚才说每个文件数据都要有文件状态,他至少要有几种状态【临时态】,【完成态】,【垃圾态】。
            当用户session关闭,或者上传新的附件之后,不要直接去清理刚才的垃圾,你可以试着把他标记为【垃圾】,晚上服务器做清理(就好像我们早上拉大便一样)的时候进行清理,这个好像叫什么来的?(扫描-标记,字眼熟悉吗?看看think in java,题外话,这就是看这些书有啥用,记住他的实现机制一点用没有,然而拿出来用在别的地方才是真的)。
    • 我怎么让客户端显示等待画面?
      面对这种问题,我只能说“凑,你想怎么弄我怎么知道,看心情”
    • 垃圾

 

 

 

 

 

 

 

 

 

 

 

 

 

待续

posted @ 2015-12-14 09:33  叶知泉  阅读(1124)  评论(2编辑  收藏  举报