HTML文件上传与下载

传统的文件下载有两种方法:

使用<a/>标签,href属性直接连接到服务器的文件路径

window.location.href="url"

这两种方法效果一样。但有个很大的问题,如果下载出现异常(连接路径失效、文件不存在、网络问题等),会导致原本的页面被覆盖掉,显示404等错误信息。

大致的优化思路如下:

使用<a/>标签HTML5新的属性download。

使用<iframe><iframe/>元素进行下载。

使用ajax、axios、fetch等方法异步下载。

使用websocket下载。

我们来逐一分析:

 <a/>标签的download属性,需要和href一起用,download的作用是为下载的文件赋文件名。

如果服务端没有指定文件名,就以此属性规定的名称命名。

如果下载出现异常,该属性的存在能够保证页面不会出问题。

如果服务端返回的不是文件、而是字符,如果download=‘’error.txt”,能够通过打开此文件查看到返回的文本信息。

<iframe>标签可以做到在现有的页面下,内嵌一个子页面。当用户点击文件下载时,将隐藏的iframe元素的src属性指向文件下载路径。

如果没有异常,文件将会直接下载。

如果出现异常,iframe子页面会报错,父页面不会受任何影响。

使用异步请求进行下载。

在网上看了看,大致的流程是:发送异步请求时设置responseType为blob,即接收流数据为blob对象保存在内存中。接收完成后,生成链接地址(1.通过FileReader对象将blob对象生成base64编码 2.通过URL.createObjectURL生成指向文件内存的链接),写入<a/>标签的href属性,然后模拟点击<a/>按标签实现下载。

此方法最大的问题是,因无法直接操作磁盘,故接收的文件必须先存放在内存中(且只有传输完成后才能构建blob对象),才能转化成文件。因此,大文件的下载可能会把你的浏览器挤爆。

使用websocket下载。

需要额外开启websocket服务,此方法未做实践。

总结以上方法,最推荐前两种,方便简单。

附上后端Django代码(适用于前两种方法):

def syncDownLoad(request): "文件下载" print("同步下载文件") startTime = time.time() def file_iterator(file, chunk_size=1024): with open(file, "rb") as f: while True: c = f.read(chunk_size) if c: yield c else: endTime = time.time() print("传输时间", endTime - startTime) break fileRoute = "/static/files/2018/12/18/第四章(1)学习动机概述.mp4" fileName = "第四章(1)学习动机概述.mp4" route = os.path.dirname(os.path.dirname(__file__)) + fileRoute if os.path.exists(route): # 如果存在文件 response = StreamingHttpResponse(file_iterator(route)) # response[\'Content-Type\'] = \'application/octet-stream\' response[\'Content-Type\'] = \'text/html\' response[\'Content-Disposition\'] = \'attachment;filename="{0}"\'.format(fileName).encode("utf-8") return response else: return HttpResponse("cannot find file")

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzzypp.html