本文共 2580 字,大约阅读时间需要 8 分钟。
最近项目较为清闲,研究了下Html5新增的几个重要技术点,如操作文件系统、获取摄像头麦克风、本地图片预览、Ajax上传文件等。灵光一现,我有了一个“墨迹”的想法:通过浏览器获取影音数据并实时存储到本地磁盘上,再接着后台默默上传该文件,达到视频录像伪实时备份的目的。然而经过两三天的琢磨研究,有一问题怎么也未能解决:从UserMedia中如何获得视音频流?(目前能力有限,先留着以后继续研究)。哎,功亏一篑啊。
不过,一事还是值得记录和分享的,那就是大文件断点续传!总体思路:用js获取文件的相关属性如name、size、type、lastModified等,发送给后台用于确定文件唯一性(我用的是它们4个的MD5散列值,最好是JS给出整个文件的MD5值);上传之前先check,看看已经上传多少字节了;后续上传时只上传未曾上传过的字节。废话不多说,上代码!注释很清晰哦!
大文件断点续传
@RequestMapping(value = "/check", method = RequestMethod.GET) @ResponseBody /** * 上传检查。 * 上传之前先check,查询已上传字节数。文件不存在就返回0 * @param request * @return */ public String check(HttpServletRequest request) { String name = request.getParameter("name"); String size = request.getParameter("size"); String type = request.getParameter("type"); String lastModified = request.getParameter("lastModified"); String fileID = new SimpleHash("MD5", name, ByteSource.Util.bytes(size + type + lastModified), 2).toHex();// 通过name、size、type、lastModified四个属性来确定文件唯一性——MD5散列值。 String fileName = fileID + "-" + name; File file = new File("D://" + fileName); if (!file.exists()) { return "0"; } else { return file.length() + ""; } } @RequestMapping(value = "/upload", method = RequestMethod.POST) @ResponseBody /** * 上传方法 * 主体就是将InputStream流中的数据写入目标文件中,注意是append * @param request * @return */ public String upload(HttpServletRequest request) { String name = request.getParameter("name"); String size = request.getParameter("size"); String type = request.getParameter("type"); String lastModified = request.getParameter("lastModified"); String fileID = new SimpleHash("MD5", name, ByteSource.Util.bytes(size + type + lastModified), 2).toHex();// 通过name、size、type、lastModified四个属性来确定文件唯一性——MD5散列值。 String fileName = fileID + "-" + name; ServletInputStream is = null; FileOutputStream os = null; File file = null; try { is = request.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); byte[] b = new byte[1024 * 1024]; file = new File("D://" + fileName); if (!file.exists()) { file.createNewFile(); } os = new FileOutputStream(file, true);// append int n = 0; while ((n = bis.read(b)) > 0) { os.write(b, 0, n); } } catch (IOException e) { e.printStackTrace(); } finally { try { os.close(); is.close(); } catch (IOException e) { e.printStackTrace(); } } return "SUCCESS"; }
断点续传老的做法是将大文件分割成N个的小文件再已Form表单形式上传,进而后台进行类似文件拼接的相关操作。效率还可以,但颗粒度就没有上面新的方法细了,哈哈。上面的新方法颗粒度直接精确到字节了。科技在发展,社会在进步,码农也能少费点脑子敲代码,留着打DOTA了!
Best Wishes For You!