第二十天咪橙、文件上傳下載實現(xiàn)

一、文件上傳

1、multer中間件

再上傳文件時美侦,我們通常會使用到他产舞。Multer用于處理multipart/form-data 類型的表單數(shù)據(jù)。首先我們先安裝它:

cnpm install multer --save

2菠剩、使用

首先在form表單中我們需要設(shè)置enctype為:multipart/form-data表單類型易猫。同時我們也需要用到fs模塊對文件重命名。下面是單文件上傳實例:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <form action="http://localhost:8080/" method="post" enctype="multipart/form-data">
            <input type="file" name="files" value="指定文件">
            <br><br>
            <input type="submit" value="上傳">
        </form>
    </body>
</html>

node代碼:

const express=require("express");
const multer=require('multer');
//初始化上傳對象
var upload=multer({dest:'./upload/'});
var fs = require('fs');


var app=express();

app.use("/",upload.single("files"),function(req,res){   //files為input type="file"的name值
    var oldFile=req.file.destination+req.file.filename; //指定舊文件
    var newFile=req.file.destination + req.file.originalname;   //指定新文件
    fs.rename(oldFile,newFile,function(err){
        if(err){
            res.send('上傳失斁咦场擦囊!');
        }else{
            res.send('上傳成功!');
        }
    });
});

app.listen(8080);

在這里我們可以指定單個文件上傳到根目錄的upload文件夾里嘴办。這里值得注意的是req.file會返回文件的基本信息:

  fieldname: ***,   //input type="file"的name值
  originalname: ***,    //用戶計算機上的文件的名稱
  encoding: '***',      //文件編碼
  mimetype: ***',       //文件的 MIME 類型
  destination: './***/',        //保存路徑
  filename: ***,        //保存在 destination 中的文件名
  path: ***,        //已上傳文件的完整路徑
  size: **      //文件大兴渤 (字節(jié)單位)

3、上傳多個文件

在HTML找中input type="file"需要加上multiple來實現(xiàn)過濾涧郊,multiple不寫參數(shù)則可以讀取·所有文件贯被。而在服務(wù)端上,我們需要將single()改為array(“name”,num);的形式來接收多個文件的上傳請求妆艘。最后對他們?nèi)窟M行重命名彤灶。在這之前我們首先看看multer支持哪些文件上傳方式:

.single(fieldname)  //接受一個以 fieldname 命名的文件。.fields(fields)
.array(fieldname[, maxCount])   //接受一個以 fieldname 命名的文件數(shù)組批旺』仙拢可以配置 maxCount 來限制上傳的最大數(shù)量。
.fields(fields) //接受指定 fields 的混合文件汽煮。fields是一個擁有name和maxCount的數(shù)組對象搏熄。
.none()     //只接受文本域。如果任何文件上傳到這個模式暇赤,將發(fā)生 "LIMIT_UNEXPECTED_FILE" 錯誤心例。
.any()  //接受一切上傳的文件。

下面我們將會演示如何上傳多個文件:
html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <form action="http://localhost:8080/" method="post" enctype="multipart/form-data">
            <input type="file" name="files" value="指定文件" multiple>
            <br><br>
            <input type="submit" value="上傳">
        </form>
    </body>
</html>

node代碼:

const express=require("express");
const multer=require('multer');
var upload=multer({dest:'./upload/'});
var fs = require('fs');


var app=express();

app.use("/",upload.array("files",5),function(req,res,next){
    req.files.forEach(function(ele,index){
        console.log(ele);
        var oldFile=ele.destination+ele.filename;   //指定舊文件
        var newFile=ele.destination+ele.originalname;   //指定新文件
        fs.rename(oldFile,newFile,function(err){
            err?console.log('上傳失斝摇止后!'):console.log('上傳成功!');
        });
    });
    res.send("成功上傳");
});

app.listen(8080);

這里溜腐,我們獲取文件信息是通過req.files來獲取译株,他是由數(shù)組構(gòu)成的對象,之后用foreach循環(huán)對其進行重命名即可挺益。

4歉糜、通過limits來限制上傳文件

Multer通過使用limits這個對象來對數(shù)據(jù)進行限制,它允許使用以下參數(shù):

Key Description Default
fieldNameSize   field 名字最大長度    100 bytes
fieldSize   field 值的最大長度    1MB
fields  非文件 field 的最大數(shù)量 無限
fileSize    在 multipart 表單中矩肩,文件最大長度 (字節(jié)單位)   無限
files   在 multipart 表單中现恼,文件最大數(shù)量  無限
parts   在 multipart 表單中,part 傳輸?shù)淖畲髷?shù)量(fields + files)    無限
headerPairs 在 multipart 表單中黍檩,鍵值對最大組數(shù) 2000
如果你上傳的文件超出這些設(shè)定叉袍,MulterError模塊將會啟用,該模塊在node_modules/multer/lib/multer-error.js上:

我們可以使用err.code定位到該錯誤刽酱,他有7種code方式喳逛,不同設(shè)置會返回不同code;

LIMIT_PART_COUNT
LIMIT_FILE_SIZE
LIMIT_FILE_COUNT
LIMIT_FIELD_KEY
LIMIT_FIELD_VALUE
LIMIT_FIELD_COUNT
LIMIT_FIELD_COUNT

下面就給大家做個簡單實例:
html依然不變,js代碼如下:

const express=require("express");
const multer=require('multer');
var upload=multer({dest:'./upload/',limits:{fileSize: 1024 * 1024 * 20,files: 5}});
var fs = require('fs');

var app=express();

app.use("/",upload.array("files",5),function(req,res,next){
    req.files.forEach(function(ele,index){
        var oldFile=ele.destination+ele.filename;   //指定舊文件
        var newFile=ele.destination+ele.originalname;   //指定新文件
        fs.rename(oldFile,newFile,function(err){
            err?console.log('上傳失斂美铩润文!'):console.log('上傳成功!');
        });
    });
    next();
    res.send("上傳成功殿怜!");
});

app.use(function(err,req,res,next){
    if (err.code==='LIMIT_FILE_SIZE'){
        res.send('File is too large');
    }else if(err.code==='LIMIT_FILE_COUNT'){
        res.send('Too many files');
    }
})

app.listen(8080);

5典蝌、ajax圖片上傳

圖片上傳實現(xiàn)步驟

通過jquery監(jiān)聽input change事件,這樣我們可以獲取到上傳的圖片流信息头谜,從而可以獲取到圖片的地址骏掀、大小、格式以及名稱等信息

這里創(chuàng)建3個數(shù)組柱告,imgName截驮、imgSrc、imgFile分別用于存放上傳圖片的名稱际度、url地址以及圖片流信息

var fileList = this.files;
        for(var i = 0; i < fileList.length; i++) {
            var imgSrcI = getObjectURL(fileList[i]);
            imgName.push(fileList[i].name);
            imgSrc.push(imgSrcI);
            imgFile.push(fileList[i]);
        }

getObjectURL方法是一個用于獲取本地圖片的地址葵袭,使用該url可以顯示圖片

function getObjectURL(file) {
    var url = null ;
    if (window.createObjectURL!=undefined) { // basic
        url = window.createObjectURL(file) ;
    } else if (window.URL!=undefined) { // mozilla(firefox)
        url = window.URL.createObjectURL(file) ;
    } else if (window.webkitURL!=undefined) { // webkit or chrome
        url = window.webkitURL.createObjectURL(file) ;
    }
    return url ;
}
控制上傳圖片大小、格式以及上傳數(shù)量
    $('#upload').on('change',function(){        
          if(imgSrc.length==4){
            return alert("最多只能上傳4張圖片");
        }
        var imgSize = this.files[0].size;  //b
        if(imgSize>1024*1024*1){//1M
            return alert("上傳圖片不能超過1M");
        }
        if(this.files[0].type != 'image/png' && this.files[0].type != 'image/jpeg' && this.files[0].type != 'image/gif'){
            return alert("圖片上傳格式不正確");
        }
    })
圖片預(yù)覽

創(chuàng)建一個addNewContent方法用于動態(tài)展示添加的圖片實現(xiàn)圖片預(yù)覽乖菱,在每次上傳圖片的時候調(diào)用該方法

function addNewContent(obj) {
    $(obj).html("");
    for(var a = 0; a < imgSrc.length; a++) {
        var oldBox = $(obj).html();
        $(obj).html(oldBox + '<li class="content-img-list-item"><img src="'+imgSrc[a]+'" alt=""><a index="'+a+'" class="hide delete-btn"><i class="ico-delete"></i></a></li>');
    }
}
圖片刪除

1.通過監(jiān)聽鼠標的mouseover事件坡锡,顯示圖片刪除按鈕

$('.content-img-list').on('mouseover','.content-img-list-item',function(){
        $(this).children('a').removeClass('hide');
    });

2.監(jiān)聽鼠標的mouseleave事件,隱藏圖片刪除按鈕

$('.content-img-list').on('mouseleave','.content-img-list-item',function(){
        $(this).children('a').addClass('hide');
    });

3.獲取圖片index下標屬性窒所,通過js的splice方法刪除數(shù)組元素娜氏,重新調(diào)用addNewContent方法遍歷圖片數(shù)組顯示預(yù)覽圖片

$(".content-img-list").on("click",'.content-img-list-item a',function(){
            var index = $(this).attr("index");
            imgSrc.splice(index, 1);
            imgFile.splice(index, 1);
            imgName.splice(index, 1);
            var boxId = ".content-img-list";
            addNewContent(boxId);
            if(imgSrc.length<4){//顯示上傳按鈕
                $('.content-img .file').show();
            }
      });
圖片上傳提交

這里主要使用FormData來拼裝好數(shù)據(jù)參數(shù),提交到后臺

var formFile = new FormData();

遍歷imgFile圖片流數(shù)組拼裝到FormData中

 $.each(imgFile, function(i, file){
            formFile.append('myFile[]', file);
        });

添加其他參數(shù)

    formFile.append("type", type); 
        formFile.append("content", content); 
        formFile.append("mobile", mobile); 

最后使用ajax提交內(nèi)容

 $.ajax({
            url: 'http://zhangykwww.yind123.com/webapi/feedback',
            type: 'POST',
            data: formFile,
            async: true,  
            cache: false,  
            contentType: false, 
            processData: false, 
            // traditional:true,
            dataType:'json',
            success: function(res) {
                console.log(res);
            }
        })

以上就實現(xiàn)了圖片上傳墩新、圖片預(yù)覽和圖片刪除的功能

jquery設(shè)置 ajax屬性

processData : false, // 告訴jQuery不要去處理發(fā)送的數(shù)據(jù)
contentType : false,// 告訴jQuery不要去設(shè)置Content-Type請求頭

二贸弥、文件下載

文件下載非常簡單,僅需通過res.download()執(zhí)行即可海渊,他可以寫為3種形式:

res.download('/report-12345.pdf');

以下是一個對選擇對應(yīng)文件進行下載的實例: html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <form action="http://localhost:8080/" method="post" enctype="application/x-www-form-urlencoded">
            <input type="file" name="files" value="選擇下載的文件"><br><br>
            <input type="submit" value="下載">
        </form>
    </body>
</html>

js:

const express=require("express");
const bodyParser=require("body-parser");

var app=express();

var jsonParser = bodyParser.json();
var urlencodedParser = bodyParser.urlencoded({ extended: false });

app.post('/',urlencodedParser,function(req,res){
    res.download("./public/"+req.body.files,err=>{
        if(err){
            res.send("下載失斆嗥!!");
        }else{
            console.log("下載成功臣疑!");
        }
    });
});

app.listen(8080);

我們可以選擇根目錄public下的文件對其進行下載盔憨。

日期:2021/12/13

學(xué)習參考視頻:*https://www.bilibili.com/video/BV1i7411G7kW?p=57&t=1403.1

學(xué)習參考文檔參考部分相關(guān)視頻文案和課件,僅供個人學(xué)習和記錄

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末讯沈,一起剝皮案震驚了整個濱河市郁岩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖问慎,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萍摊,死亡現(xiàn)場離奇詭異,居然都是意外死亡如叼,警方通過查閱死者的電腦和手機冰木,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來笼恰,“玉大人踊沸,你說我怎么就攤上這事∩缰ぃ” “怎么了逼龟?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長追葡。 經(jīng)常有香客問我审轮,道長,這世上最難降的妖魔是什么辽俗? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任疾渣,我火速辦了婚禮,結(jié)果婚禮上崖飘,老公的妹妹穿的比我還像新娘榴捡。我一直安慰自己,他們只是感情好朱浴,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布吊圾。 她就那樣靜靜地躺著,像睡著了一般翰蠢。 火紅的嫁衣襯著肌膚如雪项乒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天梁沧,我揣著相機與錄音檀何,去河邊找鬼。 笑死廷支,一個胖子當著我的面吹牛频鉴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播恋拍,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼垛孔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了施敢?” 一聲冷哼從身側(cè)響起周荐,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤狭莱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后概作,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腋妙,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年仆嗦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片先壕。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡瘩扼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垃僚,到底是詐尸還是另有隱情集绰,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布谆棺,位于F島的核電站栽燕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏改淑。R本人自食惡果不足惜碍岔,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朵夏。 院中可真熱鬧蔼啦,春花似錦、人聲如沸仰猖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饥侵。三九已至鸵赫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間躏升,已是汗流浹背辩棒。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留膨疏,地道東北人盗温。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像成肘,于是被迫代替她去往敵國和親卖局。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容