vue2和django上传和下载文件
1.vue给django传MP4(FornData)
(用FormData装提交的文件, $.ajax发送, 代理服务器跨域)
1-1.vue($.ajax + 代理服务器)
上传input组件要加type="button
,这样点击后就不会刷新页面(好像默认submit会刷新页面)
<form class="form-horizontal" id="uploadForm" method="post" action="" enctype="multipart/form-data">
<input type="file" id="file3" name="file" multiple='' accept=".mp4"/>
<input type="button" value="上传" id="submit" @click="check()">
</form>
script中,使用ajax传FormData,这里面的$是因为用了jquery
function check() {
//mp4 3gp mov
var doc = document.getElementById('file');
for(var i=0;i<doc.files.length;i++){
var name = doc.files[i].name;
var hz = name.substring(name.lastIndexOf(".")+1);
if(hz!="mp4" && hz!="3gp" && hz!="mov" && hz!="MP4" && hz!="3GP" && hz!="MOV"){
$.messager.alert("错误信息","请上传mp4、3gp、mov视频格式!!",'error');
return false;
}
}
upload();
}
function upload(){
var formData = new FormData($('#uploadForm')[0]);
$.ajax({
type: 'post',
// url: "<%=path%>/shipin/ftpupload.do",
url: "/api/api/fileUpload/upload/",
data: formData,
cache: false, //是否在缓存中读取数据的读取
processData: false, //用于对data参数进行序列化处理
contentType: false, //发送信息至服务器时内容编码类型,上传文件时设置为false
}).then(function (data) {
console.log(data)
console.log(data.msg)
if(data.msg=='Success'){
alert("上传成功!");
}else if(data==1){
$.messager.alert("错误信息","上传失败!",'error',function(){});
}else{
$.messager.alert("错误信息","请选择需要上传的文件!",'error',function(){});
}
});
}
关于跨域问题,参考:
Vue之Axios跨域问题解决方案
1-2.django
在view.py中添加如下代码,返回HttpResponse传递是否成功写入的信息
import json
import os
import re
import time
import uuid
from pathlib import Path
from django.middleware.csrf import get_token
from django.views.decorators.http import require_http_methods
@require_http_methods(["GET", "POST"])
@csrf_exempt
def returnfile(request):
print('here returnfile')
# print("request",request)
# print("request.FILES:",request.FILES.get('file'))
# return HttpResponse("这个HTTP显示还是挺有意思的!")
response = {}
try:
if request.method == 'GET':
get_token(request)
if request.method == 'POST':
req = request.FILES.get('file')
print("req:",req) # None
print("request.FILES:",request.FILES) # <MultiValueDict: {}>
print("request:",request) # <WSGIRequest: POST '/api/fileUpload/upload/'>
print("request.POST:",request.POST) # <QueryDict: {}>
# 上传文件类型过滤
# file_type = re.match(r'.*\.(txt|doc|docx)', req.name)
file_type = re.match(r'.*\.(txt|doc|docx|mp4)', req.name)
print("file_type:",file_type)
print("req.name",req.name)
if not file_type:
response['code'] = 2
response['msg'] = '文件类型不匹配, 请重新上传'
return HttpResponse(json.dumps(response))
# 将上传的文件逐行读取保存到list中
file_info = {'date': '', 'name': '', 'uuid': '', 'path': ''}
content = []
for line in req.read().splitlines():
# print("line:", line)
content.append(line)
# print("type:", type(content[0]))
# print("content[0].decode:", content[0].decode("utf-8"))
# print("req.read():", req.read())
# 打开特定的文件进行二进制的写操作
dir_path_str = "./file"
print("save_dir:",Path(os.path.abspath(dir_path_str)))
Path(dir_path_str).mkdir(exist_ok=True)
# file_path = os.path.join(dir_path_str, req.name)
file_path = os.path.join(dir_path_str, "mv.mp4")
print("file_path:",file_path)
destination = open(file_path, 'wb+')
for chunk in req.chunks(): # 分块写入文件
destination.write(chunk)
destination.close()
# 生成当前文件生成UUID
file_info['uuid'] = uuid.uuid1()
# 上传文件的时间
time_stamp = time.time()
now = int(round(time_stamp * 1000))
file_info['date'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(now / 1000))
# 文件名称
file_info['name'] = req.name
# 返回状态信息
# response['check'] = str(content[0].decode('utf-8'))
response['msg'] = "Success"
response['code'] = 200
except Exception as e:
print(e)
response['msg'] = '服务器内部错误'
response['code'] = 1
# 在前端显示为{msg: 'Success', code: 200}
return HttpResponse(json.dumps(response), content_type="application/json")
记得添加urls
2.django给vue传gif
(用axios发请求, FileResponse装服务器文件, a标签点击下载)
2-1. 在vue中
1-2-1.第一种方式
参考:找不到了
仅在vue文件的template中添加下载链接,其中href是我的后端下载链接,点击即可下载
<a href="http://127.0.0.1:8000/api/download">下载</a>
1-2-2.第二种方式
参考:找不到了
在vue文件的template中加入
<button @click="download()">下载文件</button>
在script的export const{…,methods:{}}中加入函数
import {downloadFile} from "../api/api";
export default{
name:'AboutView', // 随便一个view都行
data(){
return{
// ...
}
},
methods:{
download(){
downloadFile()
},
},
}
在…/api/api.js中(这里我改了href为自己的)
//先定义axios
export const downloadFile = () => {
return axios({
method:'get',
url:'/api/download/',
responseType: 'blob', // 表明返回服务器返回的数据类型
}).then(res => {
console.log('/api/download/的responce',res)
const content = res
const blob = new Blob([content])
const fileName = 'output.gif'
if ('download' in document.createElement('a')) { // 非IE下载
console.log("非IE下载")
const elink = document.createElement('a')
console.log("elink",elink)
elink.download = fileName
elink.style.display = 'none'
// elink.href = URL.createObjectURL(blob)
elink.href = 'http://127.0.0.1:8000/api/download'
console.log("elink.href",elink.href)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
} else { // IE10+下载
console.log("IE10+下载")
navigator.msSaveBlob(blob, fileName)
}
})
}
2-2. 在django框架的app.view.py中添加视图,注意:
因为django框架运行起来的命令是python manage.py runserver
所以文件读取都以manage.py的路径为路径
例子:
我的django后端项目的文件夹叫back,manage.py在该目录下
使用python manage.py runserver运行后端
若在app/view.py中读取face_output.gif文件
那么读的文件路径为(back)/face_output.gif(与manage.py同目路径,而不与app/view.py同路径)
@csrf_exempt
def download(request):
response = FileResponse(open(r"face_output.gif", "rb")) # 注意face_output.gif是和manage.py同目录的
response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = "attachment;filename=filename.gif" # 注意filename不支持中文
return response
记得添加urls
参考:https://blog.youkuaiyun.com/lishuaigell/article/details/124226453