美文网首页
分片视频上传

分片视频上传

作者: 苏小小北 | 来源:发表于2018-10-10 19:41 被阅读0次

对于facebook、twitter 上传视频api中,大视频都是需要分片上传,一次上传只能几Mb内, 并且是以 multipartfile/form-data 方式分片上传文件

现有两个处理方案

1.将视频文件切割成很多小文件,每个文件保持在几Mb内,但对于facebook api来说,是不可行的,facebook每次上传一个分片后,会将需要上传的startOffset和endOffset返回回来,然后再上传指定位置和长度的二进制文件,这样就需要每收到一个上传分片请求后就需要分割文件,效率较低。推荐第2种。

2.打开一个文件流,每次将指定byte 写入到post 请求的输出流中,通过文件流来控制需要上传的位置和字节数,这样只需要保证这个流存在就可以。
代码如下

/**
     * 以 multipartfile/form-data 方式分片上传文件
     * @param url post请求的url
     * @param params 需要的body参数
     * @param header 需要的header参数
     * @param bufferedInputStream 文件缓存流
     * @param startOffset 上传的起始位置(包含这个位置)
     * @param endOffset 上传的中止位置(包含这个位置)
     * @param multipartFileParam multipartFile中的name
     * @param multipartFileName multipartFile中的fileName
     * @param charset 字符集
     * @param connectTimeout 超时时长,单位毫秒
     * @param readTimeout 超时时长,单位毫秒
     * @return
     */
    public static String postChunkInputStream(String url, Map<String, String> params, Map<String, String> header,
        BufferedInputStream bufferedInputStream, Long startOffset, Long endOffset,
        String multipartFileParam, String multipartFileName,
        String charset, int connectTimeout, int readTimeout) {

//        try {
//            /**
//             * 文件输入跳到指定的开始位置
//             */
//            bufferedInputStream.skip(startOffset);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        String result = "";
        JSONObject resJson = new JSONObject();
        OutputStream out = null;
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setConnectTimeout(connectTimeout);
            connection.setReadTimeout(readTimeout);

            if (header != null) {
                for (Map.Entry<String, String> entry : header.entrySet()) {
                    connection.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }

            String boundary = "=====" + String.valueOf(new Date().getTime()) + "=====";
            connection.setRequestProperty("content-type", "multipart/form-data; boundary=" + boundary);
            out = new DataOutputStream(connection.getOutputStream());
            if (params != null && params.size() > 0) {
                StringBuilder stringBuilder = new StringBuilder();
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    stringBuilder.append("--" + boundary + "\r\n");
                    stringBuilder.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n");
                    stringBuilder.append(entry.getValue() + "\r\n");
                }
                out.write(stringBuilder.toString().getBytes(charset));
            }

            out.write(("--" + boundary + "\r\n").getBytes(charset));
            out.write(("Content-Disposition: form-data; name=\"" + multipartFileParam + "\"; filename=\"" + multipartFileName + "\"\r\n").getBytes(charset));
            out.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes(charset));

            long posOffset = startOffset;
            int readCount;
            while (endOffset - posOffset > BUFFER.length) {
                //剩余要读取的字节数要大于等于BUFFER的长度, write整个BUFFER
                readCount = bufferedInputStream.read(BUFFER);
                out.write(BUFFER, 0, readCount);
                posOffset += readCount;
            }
            if (endOffset - posOffset - 1 > 0) {
                int leftSize = (int)(endOffset-posOffset+1);
                byte[] tmpBuffer = new byte[leftSize];
                //读取剩下的不足BUFFER.length
                readCount = bufferedInputStream.read(tmpBuffer);
                out.write(tmpBuffer, 0, readCount);
                posOffset += readCount;
            }
            out.write("\r\n".getBytes(charset));

            out.write(("--" + boundary + "--\r\n").getBytes(charset));

            out.flush();
            out.close();

            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            if (connection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
                InputStream is = connection.getInputStream();
                while ((readCount = is.read(BUFFER)) > 0) {
                    bout.write(BUFFER, 0, readCount);
                }
                is.close();
            }else {
                InputStream is = connection.getErrorStream();
                while ((readCount = is.read(BUFFER)) > 0) {
                    bout.write(BUFFER, 0, readCount);
                }
                is.close();
            }
            connection.disconnect();
            result = bout.toString();
            resJson.put("code", connection.getResponseCode());
            resJson.put("data", result);
        } catch (IOException e) {
            logger.error("{}", e.getMessage(), e);
        }
        return resJson.toString();
    }

附上facebook调用代码:

public String facebookChunkedUpload(String pageOrGroupId, String filePath, String accessToken) {
        String baseUrl = "https://graph.facebook.com/" + pageOrGroupId + "/videos";
        Long fileSize = new File(filePath).length();
        Map<String, String> bodyParams = new HashMap<>();
        bodyParams.put("access_token", accessToken);
        bodyParams.put("upload_phase", "start");
        bodyParams.put("file_size", fileSize.toString());
        String initRes = HttpUtil.post(baseUrl, bodyParams);
        JSONObject initResJson = JSONObject.parseObject(initRes);
        String videoId = initResJson.getString("video_id");
        String uploadSessionId = initResJson.getString("upload_session_id");
        long startOffset = initResJson.getLong("start_offset");
        long endOffset = initResJson.getLong("end_offset");

        BufferedInputStream bufferedInputStream = null;

        try {
            bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
        }

        int chunkIndex = 0;
        while (startOffset < endOffset) {
            //上传完毕后,请求返回的startOffset = endOffset
            String multipartFileName = "chunk" + chunkIndex+".mp4";
            logger.info("hinson'log: startOffset: " + startOffset);
            logger.info("hinson'log: endOffset: " + endOffset);
            String uploadChunkRes = facebookChunkedUploadChunk(pageOrGroupId, accessToken, uploadSessionId,
                multipartFileName, bufferedInputStream, startOffset, endOffset);
            logger.info("hinson'log: uploadChunkRes: " + uploadChunkRes);
            JSONObject uploadChunkResJson = JSONObject.parseObject(uploadChunkRes);
            JSONObject data = uploadChunkResJson.getJSONObject("data");
            startOffset = data.getLong("start_offset");
            endOffset = data.getLong("end_offset");
        }

        //上传完毕,
        String finishRes = facebookChunkedUploadVideoFinish(pageOrGroupId, uploadSessionId, accessToken);
        JSONObject finishResJson = JSONObject.parseObject(finishRes);
        if (finishResJson.getBoolean("success") == true) {
            return "上传成功";
        }else {
            return "上传失败";
        }
    }

想了解详细的facebook分片上传视频,以后有空再详说

相关文章

  • 分片视频上传

    对于facebook、twitter 上传视频api中,大视频都是需要分片上传,一次上传只能几Mb内, 并且是以 ...

  • php 上传视频(分片)

    分片上传视频,网上部分博客总结的使用方法模糊不清楚,自己总结的小demo,亲测可用!粘贴代码即可使用!不懂的可以留...

  • JS分片上传

    JS分片上传 //分片上传 function ScarecrowPatchUpload (uploadPath, ...

  • 文件分片上传.md

    文件分片上传 文件分片上传的总体思路是 先将文件通过blob.slice()方法将文件切割成多个分片。然后循环上传...

  • webuploader前端分片上传

    前端分片上传附件 分片上传定义: 所谓的分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块...

  • 阿里oss文件分片上传

    OSS文件分片上传 依赖 基础参数dto 具体上传方法 小文件上传 大文件上传,分片oss自己处理 处理逻辑:前段...

  • 七牛云上传及上传方法封装

    分片及七牛云上传封装项目里面用到七牛云,有分片和简单上传 在此做下简单的记录,分享 下面是分片上传封装 proce...

  • Web Uploader + php视频分片上传

    由于最近项目中遇到有做视频上传的功能,决定写一篇文章详细说明大文件上传的原理和使用Baidu WebFE(FEX)...

  • 分片上传大视频文件

    引入css html部分 js部分 upload.php 加我微信公众号【皮蛋馅儿】,一起学习哦~

  • vue中使用分片上传视频

    结合背景:前段时间,由于赶项目没及时更新简书及博客园[https://www.cnblogs.com/huxinf...

网友评论

      本文标题:分片视频上传

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