In actual projects, the processing of pictures is often the most troublesome, whether it is the front or back, I have tried one or two small projects of uploading pictures, write down the steps, I forget later can come back to see, at the same time, I hope to help friends…

The front page

Framework: VUE + iview and other components to achieve the file function of the picture + KOA2

Use the Upload component of iView

The Upload to Upload

Upload component methods will not be described in detail, but some key points will be mentioned here

<Upload
:on-format-error="handleFormatError"
    :before-upload="handleBeforeUpload"
    :data='uploadData'// Pass multiple action="//localhost:6001/blog/admin/edit/image"</Upload>data() {
    return {
        uploadData: {
        	url: ' ', // The url articleId of the binary data:' '}}} // Use the browser's FileReader feature to compress and upload imageshandleBeforeUpload() {
    let reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onloadend = (e)=> {
        file.url = reader.result;
        this.uploadData.articleId = this.$route.query.id; this.uploadData.url = file.url; }}Copy the code

Front-end summary: using the iView component to construct the file upload image itself is not difficult, the official understanding of the API several attempts can be

Koa background Node framework

Node processed images in the background, checked online materials, and the packages formidable used for image processing, while Express used the NPM package FORMIDABLE, and KOA2 used the NPM package koA-FORMIDABLE. There was no difference between the two. The KOA-FORMIDABLE is just the repackaging and delivery of koA2 on the frame of the FORMIDABLE

Let’s first look at the browser and look at the HTTP request

Why is the HTTP request of the picture different from other, it is different, we are different, ha ha! Just get used to it

  • 1. Introduction of koa – formidable
  • 2. Download address, API
  • let form = formidable.parse(request);
  • Rename the image fs and place it in a public file
  • The picture path is put back to the front end

The steps are not complicated, but I am not familiar with the module of Node, such as the FS path module. I hope to do more small node projects in the future and get familiar with them.

The code is as follows:

// app.js
const Router = require('koa-router');
const router = new Router();
const serve = require("koa-static");

const formidable = require('koa-formidable'); // const fs = require('fs'); // const path = require('path'); // Image path app.use(serve(__dirname)) // set static file // create file, you can go to baidu fs modulelet mkdirs = (dirname, callback)=> {
    fs.exists(dirname, function(exists) {
        if (exists) {
            callback();
        } else {
            mkdirs(path.dirname(dirname), function() { fs.mkdir(dirname, callback); }); }}); }; router.post('/upload/image'.function (ctx, next) {
    let form = formidable.parse(request);
    function formImage() {
    	return new Promise((resolve, reject) => {
    		form((opt, {fields, files})=> {
        	let url = fields.url;
        	let articleId = fields.articleId;
        	let filename = files.file.name;
        	console.log(files.file.path);
        	let uploadDir = 'public/upload/';
    	        let avatarName = Date.now() + '_' + filename;
    	        mkdirs('public/upload'.function() { fs.renameSync(files.file.path, uploadDir + avatarName); // Rename resolve(config[env].host +'/' + uploadDir + avatarName)
                	// http://localhost:6001/public/upload/1513523744257_WX20171205-150757.png
                })
            })
    	})
    }
    let url = await formImage();
    return {flag: '1',msg:' ',data: url} // path returned to the front end}); app .use(router.routes()) .use(router.allowedMethods());Copy the code

The main points of


Use (serve(__dirname))

Use (serve(__dirname) + to set static paths based on personal preference'/public') 
resolve(config[env].host + '/upload/'App. use(serve(__dirname) +'/public/upload') 
resolve(config[env].host + '/' + avatarName)
Copy the code


2. Fs. exists Creates a file to store an image

Create an anonymous function to check whether the file exists, save it, create a file if not

let mkdirs = (dirname, callback)=> {
    fs.exists(dirname, function(exists) {
        if (exists) {
            callback();
        } else {
            mkdirs(path.dirname(dirname), function() { fs.mkdir(dirname, callback); }); }}); };Copy the code


3. The KOA framework has asynchrony, so we must terminate asynchronous operations with await

For async/await you can go to Baidu

function formImage() {returnNew Promise(resolve)=> {resolve(url)})}let url = await formImage();
Copy the code


Formidable process the picture and obtain the picture

formidable API

letform = formidable.parse(request); Form ((opt, obj)=> {// obj is an object with fields, files, etc.)  form((opt, {fields, File})=> {// fs.renamesync (opt1,opt2) opt1 form handles image path instead of fileds.url binary path, Opt2 is the renamed image name fs.renamesync (files.file.path, uploadDir + avatarName); Body = {data: url, MSG:' ', flag: '1'} returns to the front endCopy the code


In another project, the same code reported an error… I was confused, too

The above is in the MAC laptop operation, no error was found, but in the Windows system, it was found that the picture upload failed, a fatal error

fs.js:439
  return binding.rename(pathModule._makeLong(oldPath),
                 ^
Error: EXDEV, cross-device link not permitted 'C:\Users\CLi\AppData\Local\Temp\df99513a93a1cbfbc26e076f8ae08b92'
    at Object.fs.renameSync (fs.js:439:18)
Copy the code

Error: Rename files across partitions, causing permission problems

Error: EXDEV, cross-device link not permitted

Pump is not undefined. Pump is not undefined. Pump is not undefined

let readStream = fs.createReadStream(files.file.path)
let writeStream = fs.createWriteStream(uploadDir + avatarName);
readStream.pipe(writeStream);
Copy the code

The code is as follows:

exports.editImages = async(ctx, next)=> {
	let form = formidable.parse(ctx.request);
    form.encoding = 'utf-8';
    form.keepExtensions = true; // keep the suffix mkdirs('public/upload');
    let imgPlay = new Promise((resolve, reject) => {
	form((opt, {fields, files})=> {
	let articleId = fields.articleId;
	let filename = files.file.name;
        let avatarName = Date.now() + '_' + filename;
        let readStream = fs.createReadStream(files.file.path)
		let writeStream = fs.createWriteStream(uploadDir + avatarName);
		readStream.pipe(writeStream); // fs.rename(files.file.path, uploadDir + avatarName); Resolve ({url: config[env].host +'/' + uploadDir + avatarName
        	})
        	// http://localhost:6001/public/upload/1513523744257_WX20171205-150757.png
    })
    });
    let imageData = await imgPlay;
	ctx.body = {flag: '1' ,msg:' ',data: imageData}
}

Copy the code

Perfect solution to cross-platform book upload problem

There are still problems in the project, such as the compression problem of front-end uploading pictures, which involves multiple uploading problems, but it has not been practiced, so it is insufficient to continue updating in the future





Github address: github.com/Jaction/blo…