通过a标签配合download属性下载文件
html
1 | <!-- download属性的值是下载后的文件名,href属性的值是 后端文件下载接口地址 --> |
通过window.open()下载文件
- window.open 默认是开启一个新的窗口,一闪然后关闭,这样的用户体验不好html
1
2
3
4
5
6
7<button onclick="download()">下载</button>
<script type="text/javascript">
function download() {
window.open('http://localhost:3000/遗留问题.docx')
}
</script> - window.open 可以加上第二个参数 window.open(‘/download/1.png’, ‘_self’)。这样就会在当前窗口直接下载了。然而这样是将 url 替换当前页面的url,会触发 beforeunload 等页面事件,如果你的页面监听了该事件做一些操作的话,那就有影响。
- 那么还可以使用一个隐藏的 iframe 窗口来达到同样的效果,还可以不触发beforeunload等页面事件。html
1
2
3
4
5
6
7
8<button onclick="handleClick()">立即下载</button>
<iframe name="myIframe" style="display:none"></iframe>
<script>
const handleClick = () => {
window.open('/download/1.png', 'myIframe');
}
</script>
通过form表单下载文件
- form表单提交支持get和post两个请求方式 (a标签和window.open()只支持get方式)html
1
2
3
4<form action="/download" method="post">
<p>fileName: <input type="text" name="fileName" /></p>
<input type="submit" value="Submit" />
</form> - js动态创建form表单并提交,更灵活html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<button onclick="dynamicDownloadFile({ url: '/form', method: 'post', param: { fileName: 'note.txt' } })">form动态提交下载文件</button>
<script type="text/javascript">
const dynamicDownloadFile = ({ url, method = 'get', param = {} }) => {
const form = document.createElement('form');
form.action = url;
form.method = method;
form.target = 'blank';
Object.keys(param).forEach((item) => {
const input = document.createElement('input');
input.type = 'hidden';
input.name = item;
input.value = param[item];
form.appendChild(input);
});
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
</script> - 正常的form表单方式也会触发beforeunload事件,影响体验。可以用iframe的方式绕过html
1
2
3
4
5<form action="/form" method="post" target="innerIframe">
<p>fileName: <input type="text" name="fileName" /></p>
<input type="submit" value="Submit" />
</form>
<iframe name="innerIframe" style="display:none;"></iframe>
通过数据流形式下载文件
blob
- blob对象
- Binary Large Object,二进制大对象,是一个可以存储二进制文件的容器
- 早期数据库用blob类型存储声音、图片、二进制文件等
- 构建一个Blob对象通常有三种方式
- 通过Blob对象的构造函数来构建
- 已有的Blob对象调用slice接口切出一个新的Blob对象
- canvas API toBlob方法,把当前绘制信息转为一个Blob对象
- 服务器端通过二进制文件流的格式返回,前端将数据放进Blob对象中,并利用a标签下载文件属性将文件下载保存到本地 javascript
1
2
3
4
5
6// nodejs 服务器端
const downloadFile = ctx => {
const name = ctx.request.query.name;
ctx.response.body = fs.createReadStream(`server/file/${name}`)
}
app.use(route.get('/download', downloadFile)); // 下载文件html1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<!-- html 客户端 -->
<button onclick="download('note.txt')">下载</button>
<script type="text/javascript">
function download(filename) {
$.ajax({
url: `/download?name=${filename}`,
success(data) {
const url = window.URL.createObjectURL(new Blob([data.data]))
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', filename)
document.body.appendChild(link)
link.dispatchEvent(new MouseEvent('click'))
document.body.removeChild(link)
}
})
}
</script>
File
- File对象
- File对象继承了Blob并进行了扩展,使其能够支持使用系统上的文件
- File对象获取png,而File继承自Blob,所以也能转换为BlobURL,但是File还有一个好处就是File对象可以从页面中获取文件(input标签)
- 利用File对象下载input中的文件html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16文件:<input type="file" id="fileInput">
<button onclick="downloadFile('icon.png')">下载</button>
<script type="text/javascript">
function downloadFile(filename) {
const fileInput = document.getElementById('fileInput')
const url = window.URL.createObjectURL(fileInput.files[0])
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', filename)
document.body.appendChild(link)
link.dispatchEvent(new MouseEvent('click'))
document.body.removeChild(link)
}
</script>
- ajax:
- 在提交,请求,接收时,都是异步进行的,网页不需要刷新
- 在提交时,是在后台新建一个请求
- 必须使用js来实现,不启用js的浏览器,无法完成操作
- 在提交,请求,接收时,整个过程都是需要使用程序来对其数据进行处理
- from表单:
- 提交时是新建一个页面,哪怕是提交给自己本身的页面,也是需要刷新的
- 趋势放弃本页面,再次申请
- 是浏览器的功能,无论是否开启js,都可以提交表单
- 提交时,是根据你的表单结构自动完成,不需要代码干预