zoukankan      html  css  js  c++  java
  • nodejs 上传下载文件

    import { stat, mkdir, createWriteStream, createReadStream, unlink } from 'fs';
    import { parse as pathParser, extname, join as pathJoin } from 'path';
    import { request, get } from 'http';
    import { logger } from '@helper/helper';
    
    
    /**
     * uploadUrl = `http://${address}:${port}/xnode/file/ul?access_token=${token}`;
       downloadUrl = `http://${address}:${port}/xnode/file/dl?access_token=${token}$media_id=`;
     */
    
    async function createDownloadDir(dir) {
        const opts = process.platform == 'win32' ? { recursive: true } : {};
        return new Promise((resolve, reject) => {
            mkdir(dir, opts, err => {
                return err ? reject(err) : resolve(dir);
            })
        });
    }
    async function getFileStats(filePath) {
        return new Promise((resolve, reject) => {
            stat(filePath, (err, stats) => {
                return err ? reject(err) : resolve(stats);
            })
        });
    }
    
    class FileManager {
        constructor() {
            this._downloadDir = process.cwd() + '/download';
        }
        init(opts = {}) {
            opts = Object.assign({
                port: 8099
            }, opts);
            this._opts = opts;
            this._downloadDir = opts.downloadDir || process.cwd() + '/download';
    
            this._uploadUrl = `http://${opts.address}:${opts.port}/xnode/file/ul?access_token=${opts.token}`;
            this._downloadUrl = `http://${opts.address}:${opts.port}/xnode/file/dl?access_token=${opts.token}&media_id=`;
    
            //this._createDownloadDir(this._downloadDir);
            return this;
        }
        /**
         * 上传文件
         * @param {String} filePath 文件路径 E:\Project\cccs\cccc\public\static\imgs\app.png
         * @param {Function} onProgress 
         */
        async upload(filePath, onProgress) {
            const fd = pathParser(filePath);
            const fileName = fd.base;
            const stats = await getFileStats(filePath);
            const cb = onProgress && typeof onProgress == 'function' ? onProgress : null;
            let totalLength = stats.size;
            const opts = {
                method: 'POST',
                headers: {
                    'Content-disposition': `attachment; filename="${fileName}"`,
                    'Content-type': 'application/octet-stream', // 二进制数据流
                    'Content-length': totalLength,
                    'Connection': 'keep-alive',
                    'Transfer-Encoding': 'chunked', // 分片传输
                }
            };
            return new Promise((resolve, reject) => {
                let chunkLength = 0;
                let totalProgress = 0;
                let currProgress = 0;
                let req = request(this._uploadUrl.replace('8099', '8099'), opts, res => {
                    let data = [];
                    res.on('data', chunk => {
                        data.push(chunk);
                    }).on('end', () => {
                        req = null;
                        data = data.join();
                        return resolve(JSON.parse(data));
                    });
                });
                req.on('socket', socket => {                
                    socket.on('connect', () => {
                        let rs = createReadStream(filePath);
                        rs.on('data', chunk => {
                            chunkLength += chunk.length;
                            currProgress = (chunkLength / totalLength * 100) | 0;
                            if (currProgress != totalProgress) {
                                totalProgress = currProgress;
                                totalProgress % 5 == 0 && cb && cb(totalProgress);
                            }
                        }).on('end', () => {
                            rs.close();
                            rs = null;
                            req.end();
                        });
                        rs.pipe(req);                     
                    });
                })
                req.on('timeout', () => {
                    return reject('timeout');
                }).on('error', err => {
                    return reject(err);
                });
            });
        }
        /**
         * 下载文件
         * @param {String} fileId 文件ID
         * @param {Function} onProgress 
         */
        async download(fileId, onProgress) {
            const dir = await createDownloadDir(this._downloadDir);
            const cb = onProgress && typeof onProgress == 'function' ? onProgress : null;
            return new Promise((resolve, reject) => {
                const url = this._downloadUrl + fileId;
                let req = request(url, res => {
                    console.log(res)
                    //content-disposition: "attachment; filename="IMG_20200610_143528.jpg""
                    const totalLength = res.headers['content-length'];
                    const fileName = res.headers['content-disposition'].split('=')[1].replace(/"/g, '');
                    const extName = extname(fileName);
                    const dest = pathJoin(dir, `${fileId}${extName}`);
                    let out = createWriteStream(dest);
                    if (res.statusCode != 200) {
    
                    }
                    let chunkLength = 0;
                    let totalProgress = 0;
                    let currProgress = 0;
                    res.on('data', chunk => {
                        chunkLength += chunk.length;
                        currProgress = (chunkLength / totalLength * 100) | 0;
                        if (currProgress != totalProgress) {
                            totalProgress = currProgress;
                            totalProgress % 5 == 0 && cb && cb(totalProgress);
                        }
                    }).on('end', () => {
                        
                    });
                    out.on('finish', () => {
                        req = null;
                        out.close();
                        out = null;
                        resolve({
                            attachName: fileName,
                            attachPath: dest,
                            attachSize: totalLength
                        });
                    }).on('error', err => {
                        unlink(dest, err => { });
                        reject(err);
                    });
                    res.pipe(out);
                });
                req.on('timeout', () => {
                    return reject('timeout');
                }).on('error', err => {
                    return reject('error');
                });
                req.end();
            });
        }
    }
    export default new FileManager();
    
    function fetchProgress(url, opts = {}, onProgress) {
        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest();
            xhr.open(opts.method || 'get', url);
            for (let key in opts.headers || {}) {
                xhr.setRequestHeader(key, opts.headers[key]);
            }
            xhr.onload = e => resolve(e.target.responseText);
            xhr.onerror = reject;
            if (xhr.upload && onProgress) {
                xhr.upload.onprogress = onProgress; //上传
            }
            if ('onprogerss' in xhr && onProgress) {
                xhr.onprogress = onProgress; //下载
            }
            xhr.send(opts.body);
        });
    }
    
  • 相关阅读:
    【35.39%】【hdu 3333】Turing Tree
    【???】【???】小麦亩产一百八
    【心情】NOIP2014记忆
    【???】【???】了不起的郁杨
    【45.61%】【codeforces 701D】As Fast As Possible
    js如何找到方法在哪个js文件
    sql报句柄无效。 (异常来自 HRESULT:0x80070006 (E_HANDLE))
    webform的页面缓存
    KindleEditor上传文件报404
    什么是publickeytoken及publickeytoken的作用
  • 原文地址:https://www.cnblogs.com/zh33gl/p/13909527.html
Copyright © 2011-2022 走看看