前端
上传
前端上传主要是把文件发送过去,一般采用表单的形式,或者也可以针对上传接口发送请求
1 2 3 4 5 6
| <form action="http://127.0.0.1:5000/" enctype="multipart/form-data"> <input type="file" name="toupdate"/> # file的input不允许设置value <input type="submit" value="上传咯" /> # 按钮显示的文字 </form> # action为表单要提交到的路径, 必须填写,如果省略则默认当前页面
|
下载
a标签
1 2 3 4
| <div> <h2>法一: 通过`a`标签来实现下载 </h2> <a href="http://127.0.0.1:5000/download">ss</a> </div>
|
此外,HTML 5 里面为 <a>
标签添加了一个 download
的属性,我们可以轻易的利用它来实现下载重命名的功能。
1 2 3 4
| <div> <h2>法一: 通过`a`标签来实现下载 </h2> <a href="http://127.0.0.1:5000/download" download="something.txt">ss</a> </div>
|
JavaScript
添加a元素并点击
用 JavaScript 来下载文件也是利用这一特性来实现的,我们的 JavaScript 代码不外乎就是:
- 用 JavaScript 创建一个隐藏的
<a>
标签
- 设置它的
href
属性
- 设置它的
download
属性
- 用 JavaScript 来触发这个它的
click
事件
翻译成 JavaScript 代码就是:
1 2 3 4 5 6 7 8 9 10 11
| methods: { downit(){ var a = document.createElement('a'); var url = "http://127.0.0.1:5000/download" var filename = 'what-you-want.txt'; a.href = url; a.download = filename; a.click(); } }
|
fetch + blob
Blob 全称是 Binary large object,它表示一个类文件对象,可以用它来表示一个文件。根据 MDN 上面的说法,File API
也是基于 blob 来实现的。
我们构建 blob 的方式就是通过服务器返回的文件来创建 blob 拉!而最简单的方式就是用 fetch API
了,我们可以整合上面的例子:
1 2 3 4 5 6 7 8 9
| fetch('http://somehost/somefile.zip').then(res => res.blob().then(blob => { var a = document.createElement('a'); var url = window.URL.createObjectURL(blob); var filename = 'myfile.zip'; a.href = url; a.download = filename; a.click(); window.URL.revokeObjectURL(url); }))
|
已知下载接口URL, 并传入相应的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function downLoad(option){ fetch('http://somehost/download', options).then(res => { if (res.code === 0) { var a = document.createElement('a'); var url = res.data.url; var filename = 'myfile.zip'; a.href = url; a.download = filename; a.click(); } else { alert('You have no permission to download the file!'); } }); }
|
流程为:通过后端服务器来计算出用户的下载链接,然后再利用之前提到的动态创建 <a>
标签的方式来实现下载
跟: JS实现文件下载的三种方式—a标签下载、form表单下载、blob转换url下载中的一样,也都是先计算出资源所在真实的URL位置,然后再请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function downLoadFile(res){ const ele = document.createElement('a'); ele.setAttribute('href',res.url); ele.setAttribute('download' , 'download'); ele.click(); } window.onload = function(){ $.ajax({ url:"get-file", type:"get", dataType:'JSON' }).then(function(res){ if(res.bizNO > 0 ){ downLoadFile(res); }else{ alert(res.bizMsg); } }).always(function(){ alert("连接异常"); }) }
|
为什么要用 JavaScript 下载文件
好拉,说了半天,其实我们一直说的都是:「不要用 JavaScript 下载文件拉,限制多多,又不好用,直接用 html 就好拉,简单方便又快捷」这个论调。事实上也确实如此,但有些时候我们确实需要通过 JavaScript 来做一些预处理, 如权限校验。
下载文件前的权限校验
有些时候,我们需要对下载做一些限制,最常见的就是权限校验了,如检查该用户是否有下载的权限,是否有高速下载的权限等等。这时候,我们可以利用 JavaScript 做一些预处理。如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| fetch('http://somehost/check-permission', options).then(res => { if (res.code === 0) { var a = document.createElement('a'); var url = res.data.url; var filename = 'myfile.zip'; a.href = url; a.download = filename; a.click(); } else { alert('You have no permission to download the file!'); } });
|
参考:
Python Flask实现上传和下载接口
上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| import os from flask import Flask, request, url_for, send_from_directory from werkzeug.utils import secure_filename from flask import send_from_directory, make_response
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join(os.getcwd(), "updates")
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
html = ''' <!DOCTYPE html> <title>Upload File</title> <h1>Photo Upload</h1> <form method=post enctype=multipart/form-data> <input type=file name=file> <input type=submit value=upload> </form> <div> <a href='http://127.0.0.1:5000/download'><p>下载</p></a> </div> '''
def allowed_file(filename): """ 是否是允许上传的文件 """ return '.' in filename and \ filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
@app.route('/uploads/<filename>') def uploaded_file(filename): """ 获得上传后的链接 """ return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
@app.route('/', methods=['GET', 'POST']) def upload_file(): if request.method == 'POST': file = request.files['file'] if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) file_url = url_for('uploaded_file', filename=filename) print(file_url) return html + '<br><img src=' + file_url + '>' return html
|
下载
1 2 3 4 5
| @app.route("/download") def index(): return send_from_directory("./", "./", filename="test.txt", as_attachment=True)
|
Java实现上传下载
上传
application.properties
1 2 3 4 5 6
| # 用来指定服务器端文件大小的限制 spring.servlet.multipart.max-file-size=300MB # 用来指定客户端文件大小的限制 spring.servlet.multipart.max-request-size=300MB
fileLocation=static/files
|
FileUploadController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Value("${fileLocation}") private String fileLocation;
@PostMapping("upload") @ResponseBody public void upload(MultipartFile file) throws IOException { String realPath = ResourceUtils.getURL("classpath:").getPath() + fileLocation; File newFile = new File(realPath); if (!newFile.exists()) newFile.mkdirs(); String fileName = date.getTime() +"@" + file.getOriginalFilename(); file.transferTo(new File(newFile, fileName)); }
|
下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Value("${fileLocation}") private String fileLocation;
@GetMapping("download") public void download(String fileName, HttpServletResponse response) throws IOException { String realPath = ResourceUtils.getURL("classpath:").getPath() + fileLocation; FileInputStream inputStream = new FileInputStream(new File(realPath, fileName)); response.setHeader("content-disposition", "attachment; fileName=" + fileName); ServletOutputStream outputStream = response.getOutputStream(); int len = 0; byte[] data = new byte[1024]; while ((len = inputStream.read(data)) != -1) { outputStream.write(data, 0, len); } outputStream.close(); inputStream.close(); }
|