vue 上传文件 和 下载文件
Vue上传文件,不必使用什么element 的uplaod, 也不用什么npm上找的个人写的包,就用原生的Vue加axios就行了, 废话不多说,直接上代码:
html:
<input type="file" value="" id="file" @change="uploadConfig">
注意这里的type是file,就表示是上传文件了
js:
uploadConfig(e) { let formData = new FormData();
let data = JSON.stringify({
user: "username",
env: "dev"
})
formData.append('file', e.target.files[0]);
formData.append('data', data); // 上传文件的同时, 也可以上传其他数据 let url = this.$store.state.path + "api/tools/handle_upload_file"; let config = { headers:{'Content-Type':'multipart/form-data'} }; this.$axios.post(url,formData, config).then(function (response) { console.log(response.data) }) }
1. vue里面的axios,如果要用这种方式写,注意请求方式是method, 而不是 type:
this.$axios({ url:this.$store.state.path + "api/tools/handle_upload_file", method: "POST", // 这个地方注意 data: formData, file:e.target.files[0], processData:false, contentType:false, success:(response) => { console.log("upload_success_response:", response) } })
2. 传输文件类型,必须加上请求头: headers:{'Content-Type':'multipart/form-data'}
3. 注意axios的用法
后端(python):
def handle_upload_file(request): if request.method == "POST": file = request.FILES.get("file") # 获取文件要用request.FILES
data = request.POST.get("data") # 从POST请求中获取其他数据, 提前在formData中定义的 print file for chunk in file.chunks(): # 分块读取二进制文件的方法 print chunk return HttpResponse(json.dumps({"meta": 200, "msg": "ok"}))
关于下载文件, 本质就是创建一个a标签,把文件放在a标签中, 也可以直接把下载按钮写成a标签, 直接跳转到服务器的下载接口, 不过这样会跳转页面
看一个demo
download(){ let self = this; let url = self.$store.state.path + "tools/download_file"; let data = JSON.stringify({ user: self.$store.state.username, file_name: self.plist_file_name }); console.log("data:", data) self.$axios( { method: "post", url: url, data: data, responseType: "blob", // 指定获取数据的类型为blob } ).then( function (response) { data = response.data; // 创建a标签并点击, 即触发下载 let disposition_data = response.headers["content-disposition"] // 注意这里headers中的参数名是小写的 disposition_data = disposition_data.split(";") let download_file_name = "Untitled"
// 从 content-dispostition 中解析出文件名 for (let i=0; i<disposition_data.length; i++){ let k_v = disposition_data[i].split("=") if(k_v.length==2){ let k = k_v[0].trim(); let v = k_v[1].trim(); if(k == "filename"){ download_file_name = v } } } let url = window.URL.createObjectURL(new Blob([data])); let link = document.createElement("a"); link.style.display = "none"; link.href = url; link.setAttribute("download", download_file_name); // 下载到本地的文件名 document.body.appendChild(link); link.click() } ).catch(function (err) { console.log(err) }) }
python端代码(Django):
def download_file(request): if request.method == "POST": data = json.loads(request.body) response = {} file_name = data.get("file_name") if not file_name: response["meta"] = {"code": 400} response["error"] = {"error_msg": "parameter error, no file_path"} return HttpResponse(json.dumps(response)) file_path = "/tmp/file/" + file_name file = open(file_path, "rb") response = HttpResponse(file) response["Content-Type"] = "application/octet-stream"
response["Access-Control-Expose-Headers"] = "Content-Disposition" #不指定这个的话, 前端代码中无法从headers中读到 content-disposition
response["Content-Disposition"] = "attachment;filename={}".format(file_name) return response