vue與django(drf)實現(xiàn)文件上傳下載功能全過程
目錄
- 文件上傳功能
- 上傳后端部分
- 上傳前端部分(vue添加vue.js和node.js,設(shè)置eslint)
- 文件下載功能
- 下載后端部分
- 下載前端部分
- 總結(jié)
文件上傳功能
上傳后端部分
(一)Models.py
from django.db import modelsclass FilesModel(models.Model): //模型名(默認表名) name = models.CharField(max_length=20, default="") //name,fle是字段名(file為上傳的文件) file = models.FileField(upload_to="uploads/") //upload上傳功能實現(xiàn),to上傳后保存的路徑 class Meta:db_table = "files_storage" //自定義的表名ordering = ["-id"] //按順序排列
(二)Serializer.py
使用 Django REST framework 實現(xiàn)后端 REST API,需創(chuàng)建序列化器 serializers.py,內(nèi)容如下:
from rest_framework import serializersfrom files import models //files 是 app 的名字class FilesSerializer(serializers.ModelSerializer): class Meta:model = models.FilesModel //指定模型fields = "__all__" //指定序列化的字段名
(三)views.py
from rest_framework.viewsets import ModelViewSetfrom files import models, serializersclass FileViewSet(ModelViewSet): queryset = models.FilesModel.objects.all() //返回全部字段 serializer_class = serializers.FilesSerializer //指定序列化器類型
(四)urls
1.項目總配置路徑下(settings.py 所在的路徑)編輯根路由配置文件 urls.py
from django.contrib import adminfrom django.urls import path, includeurlpatterns = [ path("admin/", admin.site.urls), path("storage/", include("files.urls")) //網(wǎng)址前綴及指定某子app的url]
2.app為files 的路徑下新建 urls.py 文件,填寫路由配置:
from django.urls import include, pathfrom rest_framework import routersfrom files import viewsrouter = routers.DefaultRouter()router.register(r"files", views.FileViewSet) //注冊路徑urlpatterns = [ path("", include(router.urls))]
(五)測試后端api
運行后臺服務(wù) python manage.py runserver 0.0.0.0:8000,訪問 http://xx.xx.xx.xx:8000/storage/files/,界面如下:
上傳前端部分(vue添加vue.js和node.js,設(shè)置eslint)
<template> <div> <el-label>名稱</el-label> <el-input v-model="fileData.name" /> <el-upload ref="upload" drag action="http://xx.xx.xx.xx:8000/storage/files/" :data="fileData" :auto-upload="false" :on-success="onSuccess" > <i /> <div>將文件拖到此處,或<em>點擊上傳</em></div> </el-upload> <el-button size="small" type="success" @click="submitUpload">上傳到服務(wù)器</el-button> </div></template><script>export default { name: "UploadDemo", data() { return { fileData: {name: "" } } }, methods: { submitUpload() { this.$refs.upload.submit() }, onSuccess() { this.$message.success("上傳成功") } }}</script>
其中 el-upload 組件的 action 屬性用于指定后臺 API 的 URI;
:auto-upload 屬性用于設(shè)置是否自動上傳(這里設(shè)置為 false,手動觸發(fā)上傳動作);
:on-success 屬性用于指定上傳成功后觸發(fā)的方法。
submitUpload() 中的 this.$refs.upload.submit() 方法觸發(fā)文件上傳動作。
其中 el-upload 組件的 :data 屬性用于指定文件上傳時附加的數(shù)據(jù)(類型為 JavaScript 對象)。
注意:
1.env.development文件里改成BASE_API = ‘/api’
2.除增刪改查外,上傳的接口在index.vue文件里寫了,不用額外在api文件夾里加接口
3.route里的函數(shù)調(diào)用后端接口
4.前端一個頁面可對應(yīng)后端多個接口
上傳完成,后臺數(shù)據(jù)如下:
[ {"file": "http://172.20.23.34:8000/storage/files/uploads/AnyDesk.exe","id": 19,"name": "測試文件" }, {"file": "http://172.20.23.34:8000/storage/files/uploads/template.html","id": 18,"name": "" }, {"file": "http://172.20.23.34:8000/storage/files/uploads/20171215091830_55126_hSnPtZR.png","id": 17,"name": "" }]
文件下載功能
下載后端部分
views.py
@action(methods=["get", "post"], detail=True) def download(self, request, pk=None, *args, **kwargs):file_obj = self.get_object()response = FileResponse(open(file_obj.file.path, "rb"))return response
下載前端部分
download.vue
<template> <el-table :data="filelist.filter(data => !search || data.name.toLowerCase().includes(search.toLowerCase()))" > <el-table-column label="序號" prop="id" /> <el-table-column label="上傳時間" prop="date" /> <el-table-column label="上傳用戶" prop="auther" /> <el-table-column label="文件名" prop="filename" /> <el-table-column align="right" > <template slot="header"><el-input v-model="search" size="mini" placeholder="輸入關(guān)鍵字搜索"/> </template> <template slot-scope="scope"><el-button size="mini" @click="handleDown(scope.$index, scope.row)">Down</el-button><el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">Delete</el-button> </template> </el-table-column> </el-table></template><script>import { getPkgsList } from "@/api/user"import { getToken } from "@/utils/auth"import { delpkg } from "@/api/user"import axios from "axios"export default { data() { return { headers: {Authorization: "Bearer " + getToken() }, // addForm: { // // 文件的數(shù)組 // pics: [] // }, filelist: [], search: "", listLoading: true } }, created() { this.fetchPkgsList() }, methods: { handleChange(file, filelist) { this.filelist = filelist.slice(-3) }, onSuccess() { this.$message.success("上傳成功") }, fetchPkgsList() { this.listLoading = true getPkgsList().then(response => {console.log("getPkgsList ========> ", response)this.filelist = response.data.resultsthis.listLoading = false }) }, downloadFile(url, options = {}) { return new Promise((resolve, reject) => {// console.log(`${url} 請求數(shù)據(jù),參數(shù)=>`, JSON.stringify(options))axios.defaults.headers["Authorization"] = "Bearer " + getToken()axios({ method: "post", url: url, // 請求地址 data: options, // 參數(shù) responseType: "blob" // 表明返回服務(wù)器返回的數(shù)據(jù)類型}).then( response => { // console.log("下載響應(yīng)",response) resolve(response.data.result) debugger const blob = new Blob([response.data]) // console.log(blob) // let fileName = Date.parse(new Date()) + ".xlsx" // 切割出文件名 const fileNameEncode = options.filename // 解碼 const fileName = decodeURIComponent(fileNameEncode) // console.log("fileName",fileName) if (window.navigator.msSaveOrOpenBlob) { // console.log(2) navigator.msSaveBlob(blob, fileName) } else { // console.log(3) var link = document.createElement("a") link.href = window.URL.createObjectURL(blob) link.download = fileName link.click() // 釋放內(nèi)存 window.URL.revokeObjectURL(link.href) } }, err => { reject(err) }) }) }, handleDown(index, row) { const postUrl = "/api/files/" + (row.id) + "/download/" const params = { filename: row.filename } this.downloadFile(postUrl, params) }, handleDelete(index, row) { this.listLoading = true // const i = this.addForm.pics.findIndex((x) => x.pic === row.file) // this.addForm.pics.splice(i, 1) this.$confirm(`確定移除 ${row.filename}?`) delpkg(row.id).then(response => {// console.log("getPkgsList ========> ", response)// console.log(index)// console.log(this.filelist.length)this.filelist = this.filelist.slice(index, 1)this.fetchPkgsList()// console.log(this.filelist)this.listLoading = false }) } }}</script>
總結(jié)
到此這篇關(guān)于vue與django(drf)實現(xiàn)文件上傳下載功能的文章就介紹到這了,更多相關(guān)vue與django文件上傳下載內(nèi)容請搜索以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持!
相關(guān)文章: