js 读取文件夹,将文件进行切片上传,

新手上路,请多包涵

类似于给一个path路径 将路径读取切片上传 请问一下 fs读取 怎么将读取的信息转为new file呢,不是很清楚 ,

阅读 2.1k
2 个回答

你的意思是要选取文件夹 然后多上传嘛? 如果是这个 目前来说 兼容性并不好 有两种方式
一种是 <input type='file' webkitdirectory> webkitdirectory 是一个非标准的属性
一种是 showDirectoryPicker() showDirectoryPicker 是一个全新的API

/**
 * 文件上传模块
 * created by fish 2020-02-02
 */
import fileBus from '@/assets/config/fileBus';
import axios from 'axios';
import Vue from 'vue';
import config from '@/assets/config/config';
import store from '@/store';
import {Message} from 'iview';

import {api_file} from '@/assets/api/api';
const fs = require('original-fs');

let Uplaoder = (()=>{
    const chunkSize = 2097152; //分片大小
    const retry = 3; //重置次数
    const limitUploadNum = 3;//同时上传数量
    const App = require('electron').remote.app;
    let waitUploadList = [];//等待上传中的队列
    let isUploadingList = [];//正在上传的队列
    let uploadCancel = [];
    let mergeTimer = [];
   
    /**
     * 初始化
     * @param {*} option 
     */
    let init = (option,callback)=>{
        // 将每个上传的文件拉进等待队列
        waitUploadList.push(option.fileInfo);
    } 
    let resetList = (pid)=>{
        if(pid){
            for(let i=0;i<isUploadingList.length;i++){
                if(pid==isUploadingList[i].pid){
                    isUploadingList.splice(i,1);
                    break;
                }
            }            
        }
        let dbinfoArr = waitUploadList.splice(0,limitUploadNum-isUploadingList.length);
        dbinfoArr.forEach(ele=>{
            let isExis = false;
            for(let i=0;i<isUploadingList.length;i++){
                if(isUploadingList[i].pid == ele.pid){
                    isExis = true;
                    break;
                }
            }
            if(!isExis){
                isUploadingList.push(ele);
                startUpload(ele);                
            }
        });        
    }
    let startUpload = (fileInfo)=>{
        //文件上传队列
        uploadCancel[fileInfo.pid] = axios.CancelToken.source();
        chunkfile(fileInfo);     
    }
    /**
     * 生成文件基本数据
     * @param {*} option 
     */
    let createFileInfo = (option)=>{
        return new Promise((resolve)=>{
            resolve(
                {
                    pid: App.loginData.user_id+''+Date.now(),//唯一pid
                    file: option.file, //file数据
                    percent: 0, //进度
                    name: option.file.name,
                    uploadpath: option.path, //上传路径1
                    size: option.file.size,
                    user_id: App.loginData.user_id,
                    retry: 3, //重置次数
                    isCloud: store.state.isCloudFile,//内网还是外网
                    //类型 1是下载 2上传
                    file_type: 2,
                    r_bite: 0,
                    t_bite: option.file.size,
                    //4:未开始 1 上传成功 2 上传中 3 取消 -1 失败 6合并中 5文件名称非法 7文件删除或者改名
                    file_status: 4,
                    speed:0,
                    startSize:0,
                    chunk: 1, //当前 分片num
                    chunks: Math.ceil(option.file.size / chunkSize),//分片总数
                    file_path: option.file.path
                }
            )
        });
    }
    let chunkfile = (option)=>{
        uploadfile(option, 1, []);
    }
    
    /**
     * 分片文件流
     * @param {*} option 
     * @param {*} endBite 
     */
    let getFileStream = (option,endBite)=>{
        return new Promise((resolve,reject)=>{
            let start_bite = option.r_bite;
            let end_bite = start_bite+2*chunkSize;//截取流文件 初始流+4MB大小
            let bufferArr = [];
            let fileStream = fs.createReadStream(option.file_path,{
                autoClose: true,
                start: option.r_bite,
                end: end_bite
            });
           
            fileStream.on('data',function(chunk){
                bufferArr.push(chunk);
            });
            fileStream.on('end',function(){
                let slice_end_bite = chunkSize;
                if(option.chunk==option.chunks){
                    slice_end_bite = option.size-(option.chunk-1)*chunkSize;
                }
                var reader = Buffer.concat(bufferArr);
                let result = reader.slice(0,slice_end_bite);
                let myfile = new File([result],option.name,{type:option.file.type});
                option.receive_stream = myfile;
                option.endBite = option.r_bite+myfile.size;   
                resolve(option);
            })
            fileStream.on('error',function(error){
                fileBus.$emit('fileUploadSuccess',{
                    pid: option.pid,
                    percent: 0,
                    name: option.name,
                    speed: 0,
                    r_bite: option.r_bite,
                    t_bite: option.size,
                    status: 7,
                    chunk: option.chunk-1,
                    chunks: option.chunks,
                });
                resetList(option.pid);
                return;
            });
        });
    }

    let uploadfile = (_option)=>{
        let endBite = 0;
        if(_option.chunk<_option.chunks){
            endBite = _option.chunk*chunkSize;
        }else{
            endBite = _option.size;
        }
        let upedSize = 0;
        if(_option.chunk<=_option.chunks){
            getFileStream(_option,endBite).then((option)=>{
                option.startSize = 0;
                option.startTime = new Date().getTime();
                let formatData = new FormData();
                formatData.append('file',option.receive_stream);
                formatData.append('path',option.uploadpath);
                formatData.append('fname',option.name);
                formatData.append('file_md5', option.pid);
                formatData.append('chunk', option.chunk-1);
                formatData.append('chunks',option.chunks); 
                let url= option.isCloud?'/file/file/v1/upload':'/file/v1/upload';
                let instance = axios.create({
                    baseURL: option.isCloud?config.baseUrl:config.localBaseUrl,
                    timeout: 30000
                });
               
                instance({
                    url: url,
                    method:'post',
                    data: formatData,
                    headers:{
                        Authorization: "bearer " + (option.isCloud?App.loginData.token.token:App.loginData.internal_token),
                        "Content-Type":"multipart/form-data"
                    },
                    cancelToken: uploadCancel[option.pid].token,                  
                    onUploadProgress:(e)=>{        
                        let currentTime = new Date().getTime();
                        var timeUsed = currentTime-option.startTime;
                        upedSize= option.r_bite+e.loaded;
                        let speed = (e.loaded / timeUsed * 1000).toFixed(0) || 0;
                        
                        let percent  = parseInt((parseInt(option.r_bite) / parseInt(option.size) * 100));
                        fileBus.$emit('fileUploadProcess',{
                            pid: option.pid,
                            percent: percent,
                            name: option.name,
                            speed: speed,
                            r_bite: upedSize,
                            t_bite: option.size,
                            status: 2,
                            chunk: option.chunk-1,
                            chunks: option.chunks,
                        });
                    }
                }).then(res=>{
                    if(res.status==200){
                        if(res.data.code=='40004'){
                            fileBus.$emit('fileUploadSuccess',{
                                pid: option.pid,
                                percent: 0,
                                name: option.name,
                                speed: 0,
                                r_bite: 0,
                                t_bite: option.size,
                                status: 5,
                                chunk: 0,
                                chunks: option.chunks,
                            });
                            resetList(option.pid);
                            return;
                        }   
                        if(res.data.code=='40005'){
                            fileBus.$emit('fileUploadSuccess',{
                                pid: option.pid,
                                percent: 0,
                                name: option.name,
                                speed: 0,
                                r_bite: 0,
                                t_bite: option.size,
                                status: -1,
                                chunk: 0,
                                chunks: option.chunks,
                            });
                            resetList(option.pid);
                            return;
                        }
                        if(res.data.code ==0){     
                            option.r_bite = option.endBite;
                            option.startSize = upedSize;
                            if(res.data.data.key){
                                //小文件
                                fileBus.$emit('fileUploadSuccess',{
                                    pid: option.pid,
                                    percent: 100,
                                    name: option.name,
                                    speed: 0,
                                    r_bite: option.size,
                                    t_bite: option.size,
                                    status: 1,
                                    chunk: option.chunk-1,
                                    chunks: option.chunks,
                                });
                                resetList(option.pid);
                                return;
                            } 
                            //分片
                            if(res.data.data.is_merge){
                                mergeFile(option);
                                resetList(option.pid);
                                return;
                            }
                            if(option.chunk == option.chunks){
                                mergeFile(option);
                            }
                            ++option.chunk;
                            uploadfile(option);
                        }else{                
                            --option.retry;
                            if(option.retry>0){
                                uploadfile(option);
                            }else{
                                fileBus.$emit('fileUploadSuccess',{
                                    pid: option.pid,
                                    percent: 0,
                                    name: option.name,
                                    speed: 0,
                                    r_bite: option.r_bite,
                                    t_bite: option.size,
                                    status: -1,
                                    chunk: option.chunk-1,
                                    chunks: option.chunks,
                                });
                                resetList(option.pid);
                            }
                        }
                    }else{
                        --option.retry;
                        if(option.retry>0){
                            uploadfile(option);
                        }else{
                            fileBus.$emit('fileUploadSuccess',{
                                pid: option.pid,
                                percent: 0,
                                name: option.name,
                                speed: 0,
                                r_bite: option.r_bite,
                                t_bite: option.size,
                                status: -1,
                                chunk:option.chunk-1,
                                chunks: option.chunks,
                            });
                            resetList(option.pid);
                        }
                    }
                }).catch(err=>{
                    if(err.message == 'pause'){  
                        let percent = parseInt((parseInt(option.r_bite) / parseInt(option.size) * 100));
                        fileBus.$emit('fileUploadSuccess',{
                            pid: option.pid,
                            percent: percent,
                            name: option.name,
                            speed: 0,
                            r_bite: option.r_bite,
                            t_bite: option.size,
                            status: 3,
                            chunk: option.chunk-1,
                            chunks: option.chunks,
                        });
                        resetList(option.pid);
                        return;
                    }
                    --option.retry;
                    if(option.retry>0){
                        uploadfile(option);
                    }else{
                        fileBus.$emit('fileUploadSuccess',{
                            pid: option.pid,
                            percent: 0,
                            name: option.name,
                            speed: 0,
                            r_bite: option.r_bite,
                            t_bite: option.size,
                            status: -1,
                            chunk: option.chunk-1,
                            chunks: option.chunks,
                        });
                        resetList(option.pid);
                    }
                });  
            });
        }
    }
    /**
     * 合并文件
     * @param {*} option 
     * @param {*} file 
     * @param {*} chunk 
     * @param {*} chunks 
     */
    let mergeFile = (option)=>{
        fileBus.$emit('fileUploadSuccess',{
            pid: option.pid,
            percent: 100,
            name: option.name,
            speed: 0,
            r_bite: option.size,
            t_bite: option.size,
            status: 6,
            chunk: option.chunk,
            chunks: option.chunks,
        });

        let url = (option.isCloud?config.baseUrl:config.localBaseUrl)+(option.isCloud?'/file':'')+'/file/v1/mergefile'; 
        axios({
            url:url,
            method:'post',
            headers:{
                "Authorization":'bearer '+(option.isCloud?App.loginData.token.token:App.loginData.internal_token)
            },
            data:{
                fname: option.name,
                path: option.uploadpath,
                file_md5: option.pid,
                hide_loading: true
            }
        }).then(res=>{
            if(res.code==0){
                checkFileMergeState(res.data.hash,option);     
            }else{
                fileBus.$emit('fileUploadSuccess',{
                    pid: option.pid,
                    percent: 0,
                    name: option.name,
                    speed: 0,
                    r_bite: 0,
                    t_bite: option.size,
                    status: -1,
                    chunk: 0,
                    chunks: 0,
                });
                resetList(option.pid);
            }
        }).catch(err=>{
            fileBus.$emit('fileUploadSuccess',{
                pid: option.pid,
                percent: 100,
                name: option.name,
                speed: 0,
                r_bite: option.size,
                t_bite: option.size,
                status: -1,
                chunk:option.chunk,
                chunks: option.chunks,
            });
            resetList(option.pid);
        });
    }
    /**
     * 检测文件合并状态
     * @param {*} data 
     * @param {*} deleteData 
     */
    let checkFileMergeState = (hash,option)=>{
        return new Promise((resolve,reject)=>{
            if(mergeTimer[option.pid] != null){
                clearTimeout(mergeTimer[option.pid]);
                mergeTimer[option.pid] =null;
                delete mergeTimer[option.pid];
            }
            let numCount=0;
            mergeTimer[option.pid] = setInterval(() => {
                api_file.checkFileMergeState({
                    hide_loading: true,
                    hash: hash,
                    isCloud: option.isCloud
                }).then(res=>{
                    if(res.code==0){
                        if(res.data.status==1){
                            clearInterval(mergeTimer[option.pid]);
                            mergeTimer[option.pid] = null;
                            delete mergeTimer[option.pid]
                            fileBus.$emit('fileUploadSuccess',{
                                pid: option.pid,
                                percent: 100,
                                name: option.name,
                                speed: 0,
                                r_bite: option.size,
                                t_bite: option.size,
                                status: 1,
                                chunk: option.chunk,
                                chunks: option.chunks,
                            });
                            resetList(option.pid);
                        }else if(res.data.status == 0){
                            numCount++;
                            if(numCount<100){
                                fileBus.$emit('fileUploadSuccess',{
                                    pid: option.pid,
                                    percent: 100,
                                    name: option.name,
                                    speed: 0,
                                    r_bite: option.size,
                                    t_bite: option.size,
                                    status: 6,
                                    chunk: option.chunk,
                                    chunks: option.chunks,
                                });
                            }else{
                                clearInterval(mergeTimer[option.pid]);
                                mergeTimer[option.pid] = null;
                                delete mergeTimer[option.pid]
                                fileBus.$emit('fileUploadSuccess',{
                                    pid: option.pid,
                                    percent: 100,
                                    name: option.name,
                                    speed: 0,
                                    r_bite: option.size,
                                    t_bite: option.size,
                                    status: -1,
                                    chunk: option.chunk,
                                    chunks: option.chunks,
                                });
                                resetList(option.pid);
                            }
                        }else{
                            clearInterval(mergeTimer[option.pid]);
                            mergeTimer[option.pid] = null;
                            delete mergeTimer[option.pid];
                            fileBus.$emit('fileUploadSuccess',{
                                pid: option.pid,
                                percent: 100,
                                name: option.name,
                                speed: 0,
                                r_bite: option.size,
                                t_bite: option.size,
                                status: -1,
                                chunk: option.chunk,
                                chunks: option.chunks,
                            });
                            resetList(option.pid);
                        }
                    }else{
                        clearInterval(mergeTimer[option.pid]);
                        mergeTimer[option.pid] = null;
                        delete mergeTimer[option.pid];
                        fileBus.$emit('fileUploadSuccess',{
                            pid: option.pid,
                            percent: 100,
                            name: option.name,
                            speed: 0,
                            r_bite: option.size,
                            t_bite: option.size,
                            status: -1,
                            chunk: option.chunk,
                            chunks: option.chunks,
                        });
                        resetList(option.pid);
                    }
                });
            }, 3000);
        });
    }
    /**
     * 中止及删除文件
     * @param {*} data 
     * @param {*} deleteData 
     */
    let abortFileUpload = (data,deleteData)=>{
        for(let i=0;i<waitUploadList.length;i++){
            //如果删除的文件处于等待队列中 就需要把队列中的也删掉
            if(waitUploadList[i].pid == data.pid){
                waitUploadList.splice(i,1);
                break;
            }
        }
        //合并中止
        if(mergeTimer[data.pid]){
            clearInterval(mergeTimer[data.pid]);
            delete mergeTimer[data.pid];
        }
        //上传中止
        if(uploadCancel[data.pid]){
            uploadCancel[data.pid].cancel('pause');
        }
        if(deleteData){
            let keys = 'ecis'+App.loginData.user_id+'.'+data.pid
            Vue.fileStore.delete(keys)
            deleteData();
        }else{
            fileBus.$emit('fileUploadSuccess',{
                pid: data.pid,
                percent: data.percent,
                name: data.name,
                speed: 0,
                r_bite: data.r_bite,
                t_bite: data.t_bite,
                status: 3,
                chunk: data.chunk,
                chunks: data.chunks,
            });
        }  
        resetList(data.pid);
    }
    /**
     * 重新上传
     * @param {*} data 
     */
    let reFileUpload = (_fileInfo)=>{
        let fileInfo = JSON.parse(JSON.stringify(_fileInfo));
        if(fs.existsSync(fileInfo.file.path)){
            fileInfo.retry = retry;
            ++fileInfo.chunk;
            uploadCancel[fileInfo.pid] = axios.CancelToken.source();
            uploadfile(fileInfo);       
        }else{
            Message.info('本地文件已删除,请重新上传');
            fileBus.$emit('removeFile',fileInfo);
        }
    }
    /**
     * 中止全部
     */
    let abortAll = ()=>{
        for(let key in uploadCancel){
            uploadCancel[key].cancel('pause');
        } 
    }
    return {
        init,
        abortFileUpload,
        reFileUpload,
        abortAll,
        resetList,
        createFileInfo
    }
})();

export default Uplaoder;

createReadStreamimage.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题