美文网首页
视频切片上传

视频切片上传

作者: smallestt | 来源:发表于2018-01-30 16:46 被阅读0次

    主要用于大视频的切片上传

    主要实现步骤:

    • 声明变量
       private static int chunks = 0;//视频一共切了多少片
       private static int chunk = 0;//当前上传的是第几片
       private static int index = 1;//当前上传的是第几片
       public static int r = new Random().nextInt();//参数(根据实际情况添加)
    
    • 获取视频信息的工具类
    public class FileAccessI implements Serializable {
    
        RandomAccessFile oSavedFile;
        long nPos;
        public FileAccessI() throws IOException {
            this("", 0);
        }
    
        public FileAccessI(String sName, long nPos) throws IOException {
            oSavedFile = new RandomAccessFile(sName, "rw");
            oSavedFile.seek(nPos);
        }
    
        public synchronized int write(byte[] b, int nStart, int nLen) {
            int n = -1;
            try {
                oSavedFile.write(b, nStart, nLen);
                n = nLen;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return n;
        }
    
        //获取文件长度
        public synchronized Detail getContent(long nStart) {
            Detail detail = new Detail();
            detail.b = new byte[1024*1024*5];
            try {
                oSavedFile.seek(nStart);
                detail.length = oSavedFile.read(detail.b);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return detail;
        }
    
        public class Detail {
            public byte[] b;
            public int length;
        }
    
        public long getFileLength() {
            Long length = 0l;
            try {
                length = oSavedFile.length();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return length;
        }
    }
    
    • 视频切片
    /**
     * 视频切片上传
     * */
    public class BlockStreamBody extends AbstractContentBody {
        //给MultipartEntity看的2个参数
        private long blockSize = 0;//本次分块上传的大小
        private String fileName = null;//上传文件名
        //writeTo需要的3个参数
        private int chunks = 0, chunk = 0;//blockNumber分块数;blockIndex当前第几块
        private File targetFile = null;//要上传的文件
    
        private BlockStreamBody(String mimeType) {
            super(mimeType);
            // TODO Auto-generated constructor stub
        }
    
        /**
         * 自定义的ContentBody构造子
         * @param chunks 分块数
         * @param chunk 当前第几块
         * @param targetFile 要上传的文件
         */
        public BlockStreamBody(int chunks, int chunk, File targetFile) {
            this("application/octet-stream");
            this.chunks = chunks;//blockNumber初始化
            this.chunk = chunk;//blockIndex初始化
            this.targetFile = targetFile;//targetFile初始化
            this.fileName = targetFile.getName();//fileName初始化
            //blockSize初始化
            if (chunk < chunks) {//不是最后一块,那就是固定大小了
                this.blockSize = UploadGlobalConstant.CLOUD_API_LOGON_SIZE;
            } else {//最后一块
                this.blockSize = targetFile.length() - UploadGlobalConstant.CLOUD_API_LOGON_SIZE * (chunks - 1);
            }
    
    
    
        }
    
        @Override
        public void writeTo(OutputStream out) throws IOException {
            byte b[] = new byte[1024];//暂存容器
            RandomAccessFile raf  = new RandomAccessFile(targetFile, "r");//负责读取数据
            if (chunk == 1) {//第一块
                int n = 0;
                long readLength = 0;//记录已读字节数
                while (readLength <= blockSize - 1024) {//大部分字节在这里读取
                    n = raf.read(b, 0, 1024);
                    readLength += 1024;
                    out.write(b, 0, n);
                }
                if (readLength <= blockSize) {//余下的不足 1024 个字节在这里读取
                    n = raf.read(b, 0, (int)(blockSize - readLength));
                    out.write(b, 0, n);
                }
            } else if (chunk < chunks) {//既不是第一块,也不是最后一块
                raf.seek(UploadGlobalConstant.CLOUD_API_LOGON_SIZE * (chunk - 1));//跳过前[块数*固定大小 ]个字节
                int n = 0;
                long readLength = 0;//记录已读字节数
                while (readLength <= blockSize - 1024) {//大部分字节在这里读取
                    n = raf.read(b, 0, 1024);
                    readLength += 1024;
                    out.write(b, 0, n);
                }
                if (readLength <= blockSize) {//余下的不足 1024 个字节在这里读取
                    n = raf.read(b, 0, (int)(blockSize - readLength));
                    out.write(b, 0, n);
                }
            } else {//最后一块
                raf.seek(UploadGlobalConstant.CLOUD_API_LOGON_SIZE * (chunk - 1));//跳过前[块数*固定大小 ]个字节
                int n = 0;
                while ((n = raf.read(b, 0, 1024)) != -1) {
                    out.write(b, 0, n);
                }
            }
    
            //TODO 最后不要忘掉关闭out/raf
        }
    
        @Override
        public String getCharset() {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public String getTransferEncoding() {
            // TODO Auto-generated method stub
            return "binary";
        }
    
        @Override
        public String getFilename() {
            // TODO Auto-generated method stub
            return fileName;
        }
    
        @Override
        public long getContentLength() {
            // TODO Auto-generated method stub
            return blockSize;
        }
    
    }
    
     public void cutFileUpload(final String url, final String video, final String type) {
            try {
                final File uploadFile = new File(video);
                if (!uploadFile.exists()) { //视频文件不存在
                    if (null != upLoadFinishListener)
                        upLoadFinishListener.upLoadVideoError("视频文件不存在");
                    return;
                }
                FileAccessI fileAccessI = new FileAccessI(video, 0);
                Long nStartPos = 0l;
                Long length = fileAccessI.getFileLength();
    
                int mBufferSize = 1024 * 1024 * 5; // 每次处理1024 * 100字节
                long dd = length / mBufferSize;
                chunks = Integer.valueOf(dd + "") + 1;
                FileAccessI.Detail detail;
                long nRead = 0l;
                vedioFileName = generatePicName(video); // 分配一个文件名
                long nStart = nStartPos;
                ExecutorService executorService = Executors.newFixedThreadPool(chunks);
                for (int i = 0; i < chunks; i++) {
                    Runnable task = new Runnable() {
                        @Override
                        public void run() {
                            postVideo(url, video, type);
                        }
                    };
                    executorService.submit(task);
                }
                executorService.shutdown();
                while (true) {//视频所有子线程都已执行完-进行下一步操作
                    if (executorService.isTerminated()) {
                    
                        break;
                    }
                    Thread.sleep(1000);
                }
    
            } catch (Exception e) {
            }
        }
    

    分配文件名:目前只做了mp4格式和3gp格式的上传

       public String generatePicName(String videoPath) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS", Locale.CHINA);
            String filename = "";
            if (videoPath.contains("3gp"))
                filename = sdf.format(new Date(System.currentTimeMillis())) + ".3gp";
            else filename = sdf.format(new Date(System.currentTimeMillis())) + ".mp4";
            return filename;
        }
    
    • 上传视频
        public synchronized void postVideo(final String url, final String videoPath, String type) {
            HttpClient httpclient = null;
            try {
                // 链接超时,请求超时设置
                BasicHttpParams httpParams = new BasicHttpParams();
                HttpConnectionParams.setConnectionTimeout(httpParams, 10 * 1000);
                HttpConnectionParams.setSoTimeout(httpParams, 10 * 1000);
                // 请求参数设置
                httpclient = new DefaultHttpClient(httpParams);
                HttpPost post = new HttpPost(
                        url + "?type=" + type);
                MultipartEntity entity = new MultipartEntity();
                entity.addPart("rand",
                        new StringBody(r + "", Charset.forName("UTF-8")));
                entity.addPart("chunks", new StringBody(chunks + "", Charset.forName("UTF-8")));//总片数
                entity.addPart("chunk", new StringBody((chunk++) + "", Charset.forName("UTF-8")));//当前是第几片
    
                // 上传视频文件
                BlockStreamBody body = new BlockStreamBody(chunks, index++, new File(videoPath));
                entity.addPart("Filedata", body);
                post.setEntity(entity);
                HttpResponse resp = httpclient.execute(post);
                int statusCode = resp.getStatusLine().getStatusCode();
                if (statusCode == HttpStatus.SC_OK) {
                    HttpEntity resEntity = resp.getEntity();
                    String responces = EntityUtils.toString(resEntity);
                    //上传的返回结果
                    if (null != responces && !"".equals(responces)) {
                    
                    }
                    EntityUtils.getContentCharSet(resEntity);
                } else {
                }
    
            } catch (ParseException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (OutOfMemoryError e) {
    
            } finally {
                try {
                    httpclient.getConnectionManager().shutdown();
                } catch (Exception ignore) {
                }
            }
        }
    
    
    • 调用
       ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
            Runnable task = new Runnable() {
                @Override
                public void run() {
                    chunk = 0;
                    index = 1;
                    cutFileUpload(BaseUrl.videoUpUrl, videoPath, type);
                }
            };
    
            singleThreadExecutor.submit(task);
    

    相关文章

      网友评论

          本文标题:视频切片上传

          本文链接:https://www.haomeiwen.com/subject/aoeczxtx.html