webuploader 分片上传时 保存信息的java类


import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ChunksCenter {
    private volatile static Map<String, Item> chunkMap = new HashMap<String, Item>();
    private static volatile ChunksCenter instance = null;
    private static volatile Object object = new Object();

    private ChunksCenter() {
        super();
    }

    private static ChunksCenter getInstance() {
        if (instance == null) {
            synchronized (ChunksCenter.class) {
                if (instance == null) {
                    instance = new ChunksCenter();
                }
            }
        }
        return instance;
    }

    /**
     * 存放分片文件
     * @param key
     * @param chunkIndex --- 分片索引
     * @param file  --- 分片文件
     * @throws Exception
     */
    public static void putFile(String key, int chunkIndex, File file) throws Exception {
        if(key == null) {
            throw new NullPointerException("key is null, can update the key's file");
        }
        Item item = getItem(key);
        if(item == null) {
            throw new Exception("key: " + key + "has not inited!");
        } else {
            item.putFile(chunkIndex, file);
        }
    }

    /**
     * 初始化item存放该key对应的item信息
     * @param key
     * @param finalFile  --- 最终文件
     * @param filename  --- 文件名
     * @param total  --- 分片总个数
     * @param chunkSize  --- 分片大小(平均)
     * @param fileSize   --- 文件总大小
     * @throws Exception
     */
    public static void initItem(String key,  File finalFile, String filename, long total, long chunkSize, long fileSize) throws Exception {
        synchronized (object) {
            Item item = getItem(key);
            if(item == null) {
                if(chunkMap.get(key) != null) {
                    throw new Exception("key: " + key + " has inited!");
                }

                item = getInstance().new Item(finalFile, filename, total, fileSize, chunkSize);
                chunkMap.put(key, item);
            }
        }

    }


    /**
     * 根据key获取对应的item
     * @param key
     * @return
     */
    public static ChunksCenter.Item getItem(String key) {
        Item item = null;
        if(key != null) {
            item = chunkMap.get(key);
        }
        return item;
    }

    /**
     * 根据key判断是否已初始化
     * @param key
     * @return
     */
    public static boolean hasInited(String key) {
        return getItem(key) != null;
    }

    /**
     * 销毁该key的信息
     * @param key
     * @param delete --- 是否删除文件
     */
    public static void destroy(String key, boolean delete) {
        if(key != null) {
            Item item = getItem(key);
            if(item != null && delete) {
                item.deleteFiles();
            }
            chunkMap.remove(key);
        }
    }




    public class Item {
        private Map<Integer, File> filesMap = new HashMap<Integer, File>();
        private File finalFile;  //最终文件
        private String filename;  //文件名
        private long total;  //分片总数量
        private long fileSize;  //文件大小
        private long chunkSize; //平均分片大小

        private Item(File finalFile, String filename, long total, long fileSize, long chunkSize) {
            super();
            this.finalFile = finalFile;
            this.filename = filename;
            this.total = total;
            this.fileSize = fileSize;
            this.chunkSize = chunkSize;
        }

        private synchronized void putFile(Integer index, File file) {
            if(file != null && file.exists()) {   //当文件存在时
                filesMap.put(index, file);
            }
        }


        private void deleteFiles() {
            if(filesMap != null) {
                for(File file : filesMap.values()) {
                    if(file.exists()) {
                        file.delete();
                    }
                }
            }
        }


        public File getFile(Integer index) {
            return filesMap.get(index);
        }

        public List<File> getFiles() {
            return new ArrayList<File>(filesMap.values());
        }

        public List<File> getFilesSortByIndex() {
            List<File> files = new ArrayList<File>();
            if(filesMap != null) {
                for (int i = 0; i < total; i++) {
                    files.add(filesMap.get(i));
                }
            }
            return files;
        }


        /**
         * 判断map中文件个数是否与总个数相等
         * @return
         */
        public boolean hasComplete() {
            return filesMap.size() == total;
        }

        public File getFinalFile() {
            return finalFile;
        }

        public String getFilename() {
            return filename;
        }

        public long getTotal() {
            return total;
        }

        public long getFileSize() {
            return fileSize;
        }

        public long getChunkSize() {
            return chunkSize;
        }

    }

}

初始化 (当是分片上传时,判断key是否已经初始化,如果没有则进行初始化数据)

if(!ChunksCenter.hasInited(key)) { //判断key是否已初始化,无需判断是第几个分片,直接使用
    //finalFile为最终保存的文件
    ChunksCenter.initItem(key, finalFile, filename, total, chunkSize, fileSize);
}

放入分片文件数据 (需要在初始化key后使用)

ChunksCenter.putFile(key, chunkIndex, file);  //chunkIndex 第几个分片文件, file 分片文件

获取key对应的item数据 (推荐在判断分片索引是否为最后一个时使用)

 ChunksCenter.Item item = ChunksCenter.getItem(key);
 boolean result = item.hasComplete();  //判断是否完成,依据分片个数和与分片总个数是否相等
 File finalFile = item.getFinalFile();  //获取最终文件
 List<File> files = item.getFilesSortByIndex();  //获取按分片索引顺序的文件集合

销毁key数据

ChunksCenter.destroy(key, flag);  //flagtrue时删除对应key的item所记录的文件

其他: 使用junit模拟储存本地分片文件

    @org.junit.Test
    public void test2() throws IOException, IllegalAccessException {

        File srcFile = new File("d:/迅雷下载/天将雄师BD中字1.rmvb");  //原文件
        final File lastFile = new File("d:/迅雷下载/天将雄师BD中字1-thread.rmvb");  //最终的文件

        File dir = new File("d:/迅雷下载/天将雄师BD中字1");  //存放分片文件的文件夹
        File[] dirFiles = dir.listFiles();  //分片文件
        final int chunksNum = dirFiles.length;  //分片总个数
        final String key = System.currentTimeMillis() + "";
        final String filename = "天将雄师BD中字1-thread.rmvb";
        final long size = srcFile.length();  //文件大小
        final long avg = size / chunksNum;  //分片平均大小

        Map<Integer, File> fileMap = new HashMap<Integer, File>();
        int index = 0;

        for(File file : dirFiles) {
            fileMap.put(index ++, file);  //存放文件的map
        }
        final CountDownLatch doneSignal = new CountDownLatch(chunksNum); //让主线程等待所有子线程执行完毕后使用的类

        Integer[] indexArr = random(chunksNum, chunksNum, true);  //生成不重复的随机数 0-4

        for (int i = 0; i < chunksNum; i++) {
            final Integer chunkIndex = indexArr[i];
            final File file = fileMap.get(chunkIndex);
            try {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            if (!ChunksCenter.hasInited(key)) {
                                ChunksCenter.initItem(key, lastFile, filename, chunksNum, avg, size);
                            }
                            ChunksCenter.putFile(key, chunkIndex, file);
                            doneSignal.countDown(); //current thread finished! noted by latch object!
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
                thread.start();

            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        //确认所有线程任务完成,开始执行主线程的操作
        try {
            doneSignal.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        ChunksCenter.Item item = ChunksCenter.getItem(key);

        if (item != null && item.hasComplete()) {


            List<File> files = item.getFilesSortByIndex();
            System.out.println(files);

            //合并文件?...

        }

    }

    //生成随机数
    public Integer[] random(int randomVal, int arrSize, boolean startZero) throws IllegalAccessException {
        if(randomVal < arrSize) {
            throw new IllegalAccessException("randomVal should more than arrSize");
        } else if (randomVal <= 0) {
            throw new IllegalAccessException("randomVal should more than 0");
        }

        Integer[] arr = new Integer[arrSize];

        for (int i = 0; true;) {
            int val = new Random().nextInt(randomVal);
            if(!startZero) {
                val += 1;
            }
            boolean hasExist = false;
            if(i > 0) {
                for(int j = i - 1; j >= 0; j --) {
                    if (val == arr[j]) {
                        hasExist = true;
                        break;
                    }
                }
            }

            if(!hasExist) {
                arr[i ++] = val;
            }
            if(i == arrSize) {
                break;
            }
        }
        return arr;
    }    

其他: 分割文件方法

/**
     * 分割文件到指定文件夹,分割文件名称为源文件名称前缀+tailContent+索引+后缀
     * @param srcFile   --- 要分割的文件
     * @param outFileDirectory --- 输出文件夹路径
     * @param deleteOutFileDirectory  --- 是否删除已存在的输出文件夹
     * @param tailContent --- 在后缀前的内容
     * @param num  --- 分割的个数
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static void splitFile(File srcFile, String outFileDirectory,
        boolean deleteOutFileDirectory, String tailContent,
        int num) throws FileNotFoundException, IOException {
        RandomAccessFile inAccessFile = null;
        if(!srcFile.exists()) {
            throw new IllegalArgumentException("srcFile is not exist");
        } else if(!srcFile.isFile()) {
            throw new IllegalArgumentException("srcFile is not file");
        } else if(outFileDirectory == null) {
            throw new NullPointerException("outFileDirectory must be not null");
        }
        try {

            long totalSize = srcFile.length();
            long avgSize = totalSize / num;
            inAccessFile = new RandomAccessFile(srcFile, "r");

            String filename = srcFile.getName();
            int index = filename.lastIndexOf(".");
            if(tailContent == null) {
                tailContent = "";
            }
            String prefix = filename;
            String suffix = "";
            if(index >= 0) {
                prefix = prefix.substring(0, index);
                suffix = filename.substring(index);
            }

            File fileDirectory = new File(outFileDirectory);
            if(deleteOutFileDirectory && fileDirectory.exists() && fileDirectory.isDirectory()) { //删除输出的文件夹
                deleteDir(fileDirectory);
            }

            if(!fileDirectory.exists()) {
                fileDirectory.mkdirs();
            }

            byte[] bytes = new byte[1024];

            int len = -1;
            for (int i = 0; i < num; i++) {
                File outFile = new File(fileDirectory,prefix + tailContent + (i + 1) + suffix);
                RandomAccessFile outAccessFile = new RandomAccessFile(outFile, "rw");
                while ((len = inAccessFile.read(bytes)) != -1) {
                    outAccessFile.write(bytes, 0, len);
                    if(i != num - 1) {
                        if(outAccessFile.length() > avgSize) {
                            break;
                        }
                    }
                }
                outAccessFile.close();
            }

        } finally {
            if(inAccessFile != null) {
                inAccessFile.close();
            }
        }
    }


    /**
     * 删除文件夹  --- IOGroovyMethods
     * @param self
     * @return
     */
    public static boolean deleteDir(File self) {
        if(!self.exists()) {
            return true;
        } else if(!self.isDirectory()) {
            return false;
        } else {
            File[] files = self.listFiles();
            if(files == null) {
                return false;
            } else {
                boolean result = true;
                File[] arr$ = files;
                int len$ = files.length;

                for(int i$ = 0; i$ < len$; ++i$) {
                    File file = arr$[i$];
                    if(file.isDirectory()) {
                        if(!deleteDir(file)) {
                            result = false;
                        }
                    } else if(!file.delete()) {
                        result = false;
                    }
                }

                if(!self.delete()) {
                    result = false;
                }

                return result;
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WebUploader 是一个基于 HTML5 的文件上传组件,提供了丰富的上传功能和良好的用户体验。使用 WebUploader 实现批量上传文件可以通过以下步骤: 1. 引入 WebUploader 组件的 JS 和 CSS 文件。 2. 创建一个 HTML 元素作为文件上传区域。 3. 配置 WebUploader 组件,包括上传 URL、上传文件型、上传文件大小等。 4. 监听文件添加和上传成功等事件,实现相应的业务逻辑。 下面是一个简单的示例代码: HTML: ```html <div id="uploader"> <div class="file-list"></div> <div class="btns"> <div id="picker">选择文件</div> <button id="start-upload-btn" type="button">开始上传</button> </div> </div> ``` JS: ```javascript var uploader = WebUploader.create({ // 选完文件后,是否自动上传。 auto: false, // 文件接收服务端。 server: 'upload.php', // 上传文件型限制。 accept: { title: 'Images', extensions: 'gif,jpg,jpeg,bmp,png', mimeTypes: 'image/*' }, // 单个文件上传大小限制。 fileSingleSizeLimit: 5 * 1024 * 1024, // 批量上传大小总限制。 fileSizeLimit: 100 * 1024 * 1024, // 上传并发数,默认为3。 threads: 3 }); // 当文件添加进队列触发。 uploader.on('fileQueued', function(file) { $('.file-list').append('<div class="file-item">' + file.name + '</div>'); }); // 当文件上传成功触发。 uploader.on('uploadSuccess', function(file, response) { console.log('文件上传成功:' + file.name); }); // 点击开始上传按钮触发。 $('#start-upload-btn').on('click', function() { uploader.upload(); }); ``` 在上面的示例中,我们创建了一个文件上传区域,并配置了上传 URL、上传文件型、上传文件大小等信息。当用户选择文件后,文件会被添加到上传队列中。当用户点击开始上传按钮,所有文件将被批量上传到服务端。在上传过程中,我们通过监听文件上传成功事件来实现相应的业务逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值