preface

This article records what needs to be done at the front end and back end of an avatar upload function.

Front-end code:

  1. HTML part
<! <div class="upload-content"> <! <input type="file" name="file" id="upload"> <! <img SRC ="" Alt ="" id="img" style="display: none; > <! - no avatar images show that the background - > < div class = "bg - color" id = "bg - color" > < / div > < / div >Copy the code

Note: The display background above can be changed to the default image of the IMG tag, but I didn’t want to bother to find it, so I just gave it a background.

  1. The CSS part

Need to talk about the implementation idea here: Need to upload in three elements overlapping of input element at the highest level, to upload input set transparency, can’t see this button (the default styles are so ugly), so you can see there is no picture of background, but the background after click you can upload, because there is a layer of invisible input in the outermost layer. After uploading the image successfully, hide the background and show the image.

.upload-content {
    position: relative;
}
#upload{
    position: absolute;
    top: 0;
    left: 0;
    width: 50px;
    height: 50px;
    border-radius: 50%;
    opacity: 0;
    z-index: 10;
    outline: none;
    cursor: pointer;
}
.bg-color, #img{
    position: absolute;
    top: 0;
    left: 0;
    background-color: #ccc;
    width: 50px;
    height: 50px;
    border-radius: 50%;
    cursor: pointer;
}
Copy the code

Effect display:

  1. Js code:
const upload = document.getElementById("upload"); // Get input element const img = document.getelementByid ("img"); Const bgColor = document.getelementById ("bg-color"); Upload.onchange =function() {// If (upload.files && upload.files.length > 0) {// If the file is selected, Upload. files const file = upload.files[0]; / / get data file const isImg = /. JPG $|. PNG $|. GIF /. The test (. The file name); Const reader = new FileReader() readAsDataURL(file); // If (isImg) {const reader = new FileReader() readAsDataURL(file); Reader.onload = (e) => {let localSrc = e.target.result // bs64 used to display event.target.value= "// solve the problem of upload the second time cannot select the same file let RawFile = new FormData() // Declare a FormData rawfile.append ('file', file) // img. SRC = localSrc; ajax(rawFile, 'post', '/api/file/upload'); // Call upload interface}} else {console.warn(" File format is wrong!" ); }} else {console.warn(" File not uploaded!" ); } } const ajax = (params, mode, url) => { const xhr = new XMLHttpRequest(); // Declare the Ajax object xhr.open(mode, 'http://localhost:5000' + url, true); Xhr.setrequestheader ('systemType', 'supplyChain'); // This is the request header xhr.send(params) that must be set when uploading files; / / the converted FormData data into the interface XHR. The onload () = = > {const url = 'http://localhost:5000/api/file/load/' + JSON.parse(xhr.response).url; // You can preview and download the avatar address console.log(url); Img.style. display = "block"; // The img tag displays bgcolor.style. display = "none"; Img. SRC = url; // Display the uploaded image}}Copy the code

Effect display:

Back-end code:

Upload interface

  1. Install Express and Multer first
npm install express --save 
npm install multer --save
Copy the code
  1. Express and Multer were introduced
const express = require('express');
const router = express.Router();
const multer = require('multer');
Copy the code
  1. Settings are saved to that folder, as well as filename Settings
Const storage = multer.diskStorage({destination(req, file, cb) {cb(null, 'file') If you don't have it, you'll get an error, so you just need the file name, }, filename(req, file, cb) {cb(null, randomNumber(1,1000000) + '-' + file.originalname) // set the filename to save}}); // Const randomNumber = (min, Max) => {return math.floor (math.random () * (max-min) + min); }Copy the code

Note: I spliced a random number in front of the file name, because if two files have different contents but the file name is the same, the uploaded file will overwrite the uploaded file before. After adding a random number, each upload will be successful and will not be overwritten.

  1. Upload successful, return the file name
Router.post ('/upload', multer({storage: storage}).single('file'), (req, res, next) => {let data = {code: 200, url: req.file.filename } res.send(data); })Copy the code

Download the interface

  1. Introduce node’s fs and PATH modules
const fs = require('fs');
const path = require('path');
Copy the code
  1. File download concrete implementation
Router.get ('/load/:fileName', (req, res, next) => {let fileName = req.params.filename; Let filePath = path.join(__dirname, ".. /.. /file/" + fileName); Let stats = fs.statsync (filePath); let stats = fs.statsync (filePath); if(stats.isFile()){ res.set({ 'Content-Type': 'application/octet-stream; ', // tells the browser that it is returning a binary 'Content-disposition ': 'attachment; Filename =' + encodeURIComponent '(filename), // return the filename, if encodeURIComponent is not added, the filename is' content-length ': Stats. size // tells the browser the file size to return}); fs.createReadStream(filePath).pipe(res); // Return a binary stream} else {res.send(400); }})Copy the code

Front-end implementation of the download function supplement:

  1. You can use the A TAB to open the file address for file download
  2. You can use window.open to download files
  3. You can download files using Ajax:
/** * @description: * @param {string} href * @param {string} name file name * @return {*} */ const xhrDownFile = (href, name) => { let xhr = new XMLHttpRequest(); xhr.open('GET', href, true); xhr.responseType = 'blob'; xhr.onload = function() { if (this.status === 200) { let blob = this.response; let a = document.createElement('a'); let url = window.URL.createObjectURL(blob); a.href = url; a.download = name a.click(); a.remove(); } } xhr.send(); }Copy the code

Note: the above way only need to pass in the file name and access address, but can not carry token, if you want to carry token rewrite! The file preview interface mentioned above can be directly connected to the file address of window.open front-end.