【VUE案例練習】前端vue2+element-ui,后端nodo+express實現‘‘文件上傳/刪除‘‘功能

近期在做跟畢業設計相關的數據后臺管理系統,其中的列表項展示有圖片展示,添加/編輯功能有文件上傳。

“文件上傳/刪除”也是我們平時開發會遇到的一個功能,這里分享個人的實現過程,與大家交流談論~

一、準備工作

  • 本次案例使用的node版本是18.16.1
  • 前端vue2+element-ui
  • 后端使用node+express
  • 安裝對應庫:element-ui、axios、multer

注意:本篇重點介紹文件上傳的相關功能,后端express的具體使用可以看我的express專欄~

express專欄

二、前端

文件上傳組件,來自element-ui組件庫

注意:自行安裝組件庫

Element - The world's most popular Vue UI framework

關于組件,有些展示和功能需要對應設置(比如文件上傳的服務器地址,刪除后端文件等等)才可以正常使用,所以我對代碼進行了修改補充。

組件代碼

<template><div><el-uploadref="upload"action="http://localhost:4000/api/upload"  //文件上傳的接口list-type="picture-card":on-preview="handlePictureCardPreview":on-remove="handleRemove":file-list="fileList":on-change="handleFileChange":on-success="handleUploadSuccess":on-error="handleUploadError"name="file"><i class="el-icon-plus" /></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="dialogImageUrl" alt=""></el-dialog></div>
</template>

?變量和相關函數

注意:需要安裝axios(若安裝則跳過)

npm install axios
<script>
import Axios from 'axios'
export default {data() {return {dialogImageUrl: '', //預覽時展示的圖片dialogVisible: false,fileList: [] // 用于存儲文件列表}},methods: {// 生成文件預覽 URLhandleFileChange(file, fileList) {file.url = URL.createObjectURL(file.raw)this.fileList = fileList},// 刪除文件handleRemove(file, fileList) {this.fileList = fileList// 調用后端刪除接口if (file.response && file.response.data) {this.deleteFile(file.response.data)} else {this.$message.warning('文件尚未上傳成功,無法刪除')}},// 預覽圖片handlePictureCardPreview(file) {this.dialogImageUrl = file.urlthis.dialogVisible = true},// 文件上傳成功handleUploadSuccess(response, file) {console.log('文件上傳成功', response)if (response.code === 0) {// 從后端響應中獲取圖片的 URLconst imageUrl = response.data// 更新 fileList 中的文件 URLconst index = this.fileList.findIndex(f => f.uid === file.uid)if (index !== -1) {this.fileList[index].url = imageUrlthis.fileList[index].response = response // 保存后端返回的響應}this.$message.success('文件上傳成功')} else {this.$message.error('文件上傳失敗: ' + response.msg)}},// 文件上傳失敗handleUploadError(err, file) {console.error('文件上傳失敗', err)this.$message.error('文件上傳失敗')},deleteFile(filename) {// 去掉前綴 /public/static/upload/const pureFilename = filename.replace('/public/static/upload/', '')// 調用后端刪除接口Axios.delete(`http://localhost:4000/api/upload/${pureFilename}`).then(response => {if (response.data.code === 0) {this.$message.success('文件刪除成功')} else {this.$message.error('文件刪除失敗: ' + response.data.msg)}}).catch(err => {console.error('文件刪除失敗', err)this.$message.error('文件刪除失敗')})}}
}
</script>

完整代碼

?注意看:''localhost:4000''相關字眼(關于后端接口的,下文會作介紹)

<template><div><el-uploadref="upload"action="http://localhost:4000/api/upload"list-type="picture-card":on-preview="handlePictureCardPreview":on-remove="handleRemove":file-list="fileList":on-change="handleFileChange":on-success="handleUploadSuccess":on-error="handleUploadError"name="file"><i class="el-icon-plus" /></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="dialogImageUrl" alt=""></el-dialog></div>
</template><script>
import Axios from 'axios'
export default {data() {return {dialogImageUrl: '',dialogVisible: false,fileList: [] // 用于存儲文件列表}},methods: {// 生成文件預覽 URLhandleFileChange(file, fileList) {file.url = URL.createObjectURL(file.raw)this.fileList = fileList},// 刪除文件handleRemove(file, fileList) {this.fileList = fileList// 調用后端刪除接口if (file.response && file.response.data) {this.deleteFile(file.response.data)} else {this.$message.warning('文件尚未上傳成功,無法刪除')}},// 預覽圖片handlePictureCardPreview(file) {this.dialogImageUrl = file.urlthis.dialogVisible = true},// 文件上傳成功handleUploadSuccess(response, file) {console.log('文件上傳成功', response)if (response.code === 0) {// 從后端響應中獲取圖片的 URLconst imageUrl = response.data// 更新 fileList 中的文件 URLconst index = this.fileList.findIndex(f => f.uid === file.uid)if (index !== -1) {this.fileList[index].url = imageUrlthis.fileList[index].response = response // 保存后端返回的響應}this.$message.success('文件上傳成功')} else {this.$message.error('文件上傳失敗: ' + response.msg)}},// 文件上傳失敗handleUploadError(err, file) {console.error('文件上傳失敗', err)this.$message.error('文件上傳失敗')},// 刪除后端文件,參數傳遞的是文件名(經前端上傳過后,返回給前端的文件名)deleteFile(filename) {// 去掉前綴 /public/static/upload/const pureFilename = filename.replace('/public/static/upload/', '')// 調用后端刪除接口Axios.delete(`http://localhost:4000/api/upload/${pureFilename}`).then(response => {if (response.data.code === 0) {this.$message.success('文件刪除成功')} else {this.$message.error('文件刪除失敗: ' + response.data.msg)}}).catch(err => {console.error('文件刪除失敗', err)this.$message.error('文件刪除失敗')})}}
}
</script><style>
.el-upload-list__item-thumbnail {width: 100%;height: 100%;object-fit: cover;
}
</style>

三、后端

1、搭建express應用

【express-generator】01-安裝和基本使用

如果按照文章步驟(默認端口是3000,我這里設置成4000端口),則對應更換端口為4000,在創建的express項目的bin/www中進行修改。

2、新建文件夾以及文件

2.1、新建public/static/upload

這是存儲上傳文件的位置。

?2.2、新建routes/upload.js,用于撰寫路由方法

安裝multer,這是處理文件上傳的相關庫。

npm install multer

var express = require("express");
const multer = require("multer");
const { uploading } = require("../utils/tool");
const fs = require('fs');
const path = require('path');
var router = express.Router();// 文件上傳接口
router.post("/", async function (req, res, next) {// single 方法里面書寫上傳控件的 name 值uploading.single("file")(req, res, function (err) {if (err instanceof multer.MulterError) {next("上傳文件失敗,請檢查文件的大小,控制在 6MB 以內");} else {console.log("req.file>>>", req.file);const filePath = "/public/static/upload/" + req.file.filename;res.send({ code: 0, msg: "文件上傳成功", data: filePath });}})
});// 文件刪除接口
router.delete("/:filename", function (req, res, next) {const filename = req.params.filename;const filePath = path.join(__dirname, '../public/static/upload',filename);console.log("后端接收到的文件參數>>>",filename,"完整基本路徑是>>>>",filePath);fs.unlink(filePath, (err) => {if (err) {console.error("刪除文件失敗", err);return res.status(500).send({ code: 1, msg: "刪除文件失敗" });}res.send({ code: 0, msg: "文件刪除成功" });});
});module.exports = router;

2.3、新增utlis/tool.js,撰寫工具類函數

const multer = require("multer");
const path = require("path");// 設置上傳文件的引擎
const storage = multer.diskStorage({// 文件存儲的位置destination: function (req, file, cb) {cb(null, __dirname + '/../public/static/upload');},// 上傳到服務器的文件,文件名要做單獨處理filename: function (req, file, cb) {// 獲取文件名const basename = path.basename(file.originalname, path.extname(file.originalname));// 獲取后綴名const extname = path.extname(file.originalname);// 構建新的名字const newName = basename + new Date().getTime() + Math.floor(Math.random() * 9000 + 1000) + extname;cb(null, newName);}
})module.exports.uploading = multer({storage: storage,limits: {fileSize: 6000000,files: 1}
})

?3、在app.js中引入和使用

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const cors = require('cors');
// 文件上傳
const multer = require('multer');
const fs = require('fs');
// const path = require('path');var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var uploadRouter = require('./routes/upload');
var app = express();// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');// 允許所有來源訪問
app.use(cors());// 文件上傳
// const upload = multer({ dest: 'static/upload/' });
app.use(express.static(path.join(__dirname, 'public')));
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/api/upload/', uploadRouter);// error handler
app.use(function(err, req, res, next) {// set locals, only providing error in developmentres.locals.message = err.message;res.locals.error = req.app.get('env') === 'development' ? err : {};// render the error pageres.status(err.status || 500);res.render('error');
});module.exports = app;

四、測試

1、上傳文件(圖片)

?查看存儲上傳文件的位置

?2、刪除文件(圖片)

前端組件,鼠標進入到圖片區域,點擊刪除按鍵

前端作出對應提示

最后前端的文件列表也為空,成功刪除了文件。

后端查看文件夾,發現剛上傳的文件由于前端的刪除操作,也對應進行了刪除。

?

?五、總結

一些注意點

express應用默認端口號是3000,而案例演示的是4000(因為一般情況,3000端口容易被其他代碼程序給使用用,避免這種情況,可以使用一個新的端口號(或者把占用3000端口的程序都關閉))

關于文件上傳的設置,涉及到的知識點比較多,比如fs.unlink,path相關的知識,需要大家自行進行補充了解,部分知識點可以參考下方這篇博客文章。

【NODE】01-fs和path常用知識點


如果有問題,請留言評論~

如果你喜歡這篇文章,留下你的點贊和收藏~?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67678.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67678.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67678.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++中的析構器(Destructor)(也稱為析構函數)

在C中&#xff0c;析構器&#xff08;Destructor&#xff09;也稱為析構函數&#xff0c;它是一種特殊的成員函數&#xff0c;用于在對象銷毀時進行資源清理工作。以下是關于C析構器的詳細介紹&#xff1a; 析構函數的特點 名稱與類名相同&#xff0c;但前面有一個波浪號 ~&a…

VLN視覺語言導航基礎

0 概述 視覺語言導航模型旨在構建導航決策模型 π π π&#xff0c;在 t t t時刻&#xff0c;模型能夠根據指令 W W W、歷史軌跡 τ { V 1 , V 2 , . . . , V t ? 1 } \tau\{V_1,V_2,...,V_{t-1}\} τ{V1?,V2?,...,Vt?1?}和當前觀察 V t { P t , R t , N ( V t ) } V_…

AI協助探索AI新構型的自動化創新概念

訓練AI自生成輸出模塊化代碼&#xff0c;生成元代碼級別的AI功能單元代碼&#xff0c;然后再由AI組織為另一個AI&#xff0c;實現AI開發AI的能力&#xff1b;用AI協助探索迭代新構型AI將會出現&#xff0c;并成為一種新的技術路線潮流。 有限結點&#xff0c;無限的連接形式&a…

Flux的三步煉丹爐——fluxgym(三):矩陣測試

前面兩篇文章給大家介紹了如何準備素材和怎么煉丹&#xff0c;現在我們拿到訓練完成后的多個Lora怎么才能確定哪個才是我們需要的、效果最好的呢&#xff1f;答案就是使用xyz圖表測試&#xff0c;也稱為矩陣測試&#xff0c;通過控制控制變量的方法對Lora模型批量生圖&#xff…

利用Muduo庫實現簡單且健壯的Echo服務器

一、muduo網絡庫主要提供了兩個類&#xff1a; TcpServer&#xff1a;用于編寫服務器程序 TcpClient&#xff1a;用于編寫客戶端程序 二、三個重要的鏈接庫&#xff1a; libmuduo_net、libmuduo_base、libpthread 三、muduo庫底層就是epoll線程池&#xff0c;其好處是…

文件讀寫操作

寫入文本文件 #include <iostream> #include <fstream>//ofstream類需要包含的頭文件 using namespace std;void test01() {//1、包含頭文件 fstream//2、創建流對象ofstream fout;/*3、指定打開方式&#xff1a;1.ios::out、ios::trunc 清除文件內容后打開2.ios:…

C++編程語言:抽象機制:模板(Bjarne Stroustrup)

目錄 23.1 引言和概觀(Introduction and Overview) 23.2 一個簡單的字符串模板(A Simple String Template) 23.2.1 模板的定義(Defining a Template) 23.2.2 模板實例化(Template Instantiation) 23.3 類型檢查(Type Checking) 23.3.1 類型等價(Type Equivalence) …

定制Centos鏡像(二)

本章是對上篇文章的擴展&#xff1a; https://blog.csdn.net/qq_50247813/article/details/145286244 上篇文章學習了如何自定義鏡像安裝。這篇介紹如何在定制鏡像的時候安裝其他軟件&#xff1b; &#xff08;源文件參考上篇文章&#xff09; 根據上篇文章的步驟&#xff0c;…

【機器學習理論】樸素貝葉斯網絡

基礎知識&#xff1a; 先驗概率&#xff1a;對某個事件發生的概率的估計。可以是基于歷史數據的估計&#xff0c;可以由專家知識得出等等。一般是單獨事件概率。 后驗概率&#xff1a;指某件事已經發生&#xff0c;計算事情發生是由某個因素引起的概率。一般是一個條件概率。 …

Flutter 新春第一彈,Dart 宏功能推進暫停,后續專注定制數據處理支持

在去年春節&#xff0c;Flutter 官方發布了宏&#xff08;Macros&#xff09;編程的原型支持&#xff0c; 同年的 5 月份在 Google I/O 發布的 Dart 3.4 宣布了宏的實驗性支持&#xff0c;但是對于 Dart 內部來說&#xff0c;從啟動宏編程實驗開始已經過去了幾年&#xff0c;但…

計算機組成原理——存儲系統(一)

在人生的道路上&#xff0c;成功與失敗交織成一幅豐富多彩的畫卷。不論我們是面對勝利的喜悅&#xff0c;還是遭遇失敗的痛苦&#xff0c;都不能放棄對夢想的追求。正是在這種追求中&#xff0c;我們不斷地超越自我&#xff0c;不斷地突破自己的極限。只有勇往直前&#xff0c;…

前端知識速記:節流與防抖

前端知識速記&#xff1a;節流與防抖 什么是防抖&#xff1f; 防抖是一種控制事件觸發頻率的方法&#xff0c;通常用于處理用戶頻繁觸發事件的場景。防抖的核心思想是將多個連續觸發事件合并為一個事件&#xff0c;以減少執行次數。它在以下場景中特別有效&#xff1a; 輸入…

無人機圖傳模塊 wfb-ng openipc-fpv,4G

openipc 的定位是為各種模塊提供底層的驅動和linux最小系統&#xff0c;openipc 是采用buildroot系統編譯而成&#xff0c;因此二次開發能力有點麻煩。為啥openipc 會用于無人機圖傳呢&#xff1f;因為openipc可以將現有的網絡攝像頭ip-camera模塊直接利用起來&#xff0c;從而…

藍橋杯例題一

不管遇到多大的困難&#xff0c;我們都要堅持下去。每一次挫折都是我們成長的機會&#xff0c;每一次失敗都是我們前進的動力。路漫漫其修遠兮&#xff0c;吾將上下而求索。只有不斷努力奮斗&#xff0c;才能追逐到自己的夢想。不要害怕失敗&#xff0c;害怕的是不敢去嘗試。只…

【JavaEE進階】圖書管理系統 - 壹

目錄 &#x1f332;序言 &#x1f334;前端代碼的引入 &#x1f38b;約定前后端交互接口 &#x1f6a9;接口定義 &#x1f343;后端服務器代碼實現 &#x1f6a9;登錄接口 &#x1f6a9;圖書列表接口 &#x1f384;前端代碼實現 &#x1f6a9;登錄頁面 &#x1f6a9;…

【算法設計與分析】實驗8:分支限界—TSP問題

目錄 一、實驗目的 二、實驗環境 三、實驗內容 四、核心代碼 五、記錄與處理 六、思考與總結 七、完整報告和成果文件提取鏈接 一、實驗目的 掌握分支界限求解問題的思想&#xff1b;針對不同的問題&#xff0c;能夠利用分支界限法進行問題拆分和求解以及時間復雜度分析…

【3】阿里面試題整理

[1]. ES架構&#xff0c;如何進行路由以及選主 路由&#xff1a;在Elasticsearch&#xff08;ES&#xff09;中&#xff0c;默認的路由算法是基于文檔的_id。具體來說&#xff0c;Elasticsearch會對文檔的_id進行哈希計算&#xff0c;然后對分片數量取模&#xff0c;以確定該文…

【Linux】opencv在arm64上提示找不到libjasper-dev

解決opencv在arm64上提示找不到libjasper-dev的問題。 本文首發于?慕雪的寒舍 問題說明 最近我在嘗試編譯opencv&#xff0c;安裝依賴項libjasper1和libjasper-dev的時候就遇到了這個問題。在amd64平臺上&#xff0c;我們可以通過下面的命令安裝&#xff08;ubuntu18.04&…

【數據結構】_時間復雜度相關OJ(力扣版)

目錄 1. 示例1&#xff1a;消失的數字 思路1&#xff1a;等差求和 思路2&#xff1a;異或運算 思路3&#xff1a;排序&#xff0b;二分查找 2. 示例2&#xff1a;輪轉數組 思路1&#xff1a;逐次輪轉 思路2&#xff1a;三段逆置&#xff08;經典解法&#xff09; 思路3…

基于微信小程序的電子商城購物系統設計與實現(LW+源碼+講解)

專注于大學生項目實戰開發,講解,畢業答疑輔導&#xff0c;歡迎高校老師/同行前輩交流合作?。 技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;…