GoPro 12 Black HTTP 返回格式错误-TCP方式发起HTTP

由于用户反馈Gorpo 12 无法下载文件,遂公司买了一个来测试

发现HTTP请求报错:

java.net.ProtocolException: Unexpected status line: gpHttpServer: [04327868][INFO ] conn 0:
/videos/DCIM/100GOPRO/GX012560.MP4 @civetweb.c:17872

通过TCP方式手动请求接口发现其返回如下内容:

gpHttpServer: [UTILS_UpdateRecordingStatus:  94] record mode detected
HTTP/1.1 503 Service Unavailable
Content-Type: application/json
Content-Length: 32

{ "message": "Camera is busy" }

返回内容的第一行不包含HTTP状态码,不符合HTTP协议,所以HTTP请求被判定为失败。

后修改为用TCP手动发起HTTP请求并手动解析返回数据:

private Pair<String, String> call(){

            String requestString = "GET /gopro/media/list HTTP/1.1\nHost: " + goProIp + ":8080\n\n";
            byte[] requestBytes = requestString.getBytes(StandardCharsets.US_ASCII);

            try {
                Socket socket = new Socket(goProIp, 8080);
                OutputStream outputStream = socket.getOutputStream();
                outputStream.write(requestBytes);

                StringBuilder builder = new StringBuilder();

                while (true) {
                    if (socket.isClosed()) break;
                    final byte[] buffer = new byte[1024];
                    InputStream InputStream = socket.getInputStream();
                    final int len = InputStream.read(buffer);
                    if (len > 0) {
                        byte[] sub = new byte[len];
                        System.arraycopy(buffer, 0, sub, 0, len);
                        String data = new String(sub);
                        builder.append(data);
                    } else {
                        break;
                    }
                }
                String fullData = builder.toString();
                Log.e("fullData--" , fullData);
                if(TextUtils.isEmpty(fullData)){
                    return null;
                }

                int httpIndex = fullData.indexOf("HTTP/");

                if(httpIndex < 0) return null;

                String realHttpData = fullData.substring(httpIndex);

                if(TextUtils.isEmpty(realHttpData)) return null;

                int firstSpaceIndex = realHttpData.indexOf(" ");

                if(firstSpaceIndex < 0) return null;

                String httpCode = realHttpData.substring(firstSpaceIndex + 1, firstSpaceIndex + 4);

                if(TextUtils.isEmpty(httpCode)) return null;

                //定位body
                int doubleCrlfIndex = realHttpData.indexOf("\r\n\r\n");

                if(doubleCrlfIndex < 0) return null;

                //观察数据发现最后一个字符为换行符\r,所以去掉
                String httpBody = realHttpData.substring(doubleCrlfIndex + 4, realHttpData.length() -1);

                return new Pair<>(httpCode, httpBody);

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

下载文件:

String requestString = "GET /videos/DCIM" + goproUrlString + " HTTP/1.1\nHost: " + goProIp +":8080\n\n";
            byte[] requestBytes = requestString.getBytes(StandardCharsets.US_ASCII);

            try {
                Socket socket;
                try{
                    socket = new Socket(goProIp, 8080);
                }catch (Throwable throwable){
                    throwable.printStackTrace();
                    return null;
                }

                OutputStream outputStream = socket.getOutputStream();
                outputStream.write(requestBytes);

                //接收数据

                //接收http头
                StringBuilder builder = new StringBuilder();

                //接收body
                File mFilePath = AlbumUtil.randomCache(strings[0]);
                FileOutputStream fileOutputStream = new FileOutputStream(mFilePath);

                byte[] buffer = new byte[1024];
                InputStream inputStream = socket.getInputStream();

                boolean isDoubleCrLfFound = false;
                boolean isLastSegmentHasCrOrLf = false;
                int lastSegmentCrLfLength = 0;

                while (true){
                    if(socket.isClosed()) break;
                    int len = inputStream.read(buffer);
                    if(len > 0){
                        byte[] sub = new byte[len];
                        System.arraycopy(buffer, 0, sub, 0, len);

                        //查找双换行(\r\n\r\n)
                        if(!isDoubleCrLfFound){
                            String temString = new String(sub, StandardCharsets.US_ASCII);

                            builder.append(temString);

                            //如果前一段包含部分\r\n\r\n
                            if(isLastSegmentHasCrOrLf && lastSegmentCrLfLength > 0){
                                if(lastSegmentCrLfLength == 3){
                                    if(temString.charAt(0) == '\n'){
                                        isDoubleCrLfFound = true;
                                        fileOutputStream.write(sub, 1, sub.length - 1);
                                    }
                                } else if(lastSegmentCrLfLength == 2){
                                    if(temString.startsWith("\r\n")){
                                        isDoubleCrLfFound = true;
                                        fileOutputStream.write(sub, 2, sub.length - 2);
                                    }
                                } else if(lastSegmentCrLfLength == 1){
                                    if(temString.startsWith("\r\r\n")){
                                        isDoubleCrLfFound = true;
                                        fileOutputStream.write(sub, 3, sub.length - 3);
                                    }
                                }
                            }


                            int doubleCrLfIndex = temString.indexOf("\r\n\r\n");
                            if(doubleCrLfIndex < 0 && !isDoubleCrLfFound){
                                //确认是否最后几个字节为双换行的一部分
                                if(len > 3){
                                    String last3Char = temString.substring(temString.length()-3);
                                    if(last3Char.equals("\r\n\r")){
                                        isLastSegmentHasCrOrLf = true;
                                        lastSegmentCrLfLength = 3;
                                    }else if(last3Char.substring(1).equals("\r\n")){
                                        isLastSegmentHasCrOrLf = true;
                                        lastSegmentCrLfLength = 2;
                                    }else if(last3Char.substring(2).equals("\r")){
                                        isLastSegmentHasCrOrLf = true;
                                        lastSegmentCrLfLength = 1;
                                    }
                                }
                            } else {
                                isDoubleCrLfFound = true;
                                fileOutputStream.write(sub, doubleCrLfIndex + 4, sub.length - doubleCrLfIndex - 4);
                            }
                        }else {
                            fileOutputStream.write(sub);
                        }
                    }else {
                        break;
                    }
                }

                fileOutputStream.close();

                String fullData = builder.toString();

                Log.e("fullData--" , fullData);
                if(TextUtils.isEmpty(fullData)){
                    return null;
                }

                int httpIndex = fullData.indexOf("HTTP/");

                if(httpIndex < 0) return null;

                String realHttpData = fullData.substring(httpIndex);

                if(TextUtils.isEmpty(realHttpData)) return null;

                int firstSpaceIndex = realHttpData.indexOf(" ");

                if(firstSpaceIndex < 0) return null;

                String httpCode = realHttpData.substring(firstSpaceIndex + 1, firstSpaceIndex + 4);

                if(TextUtils.isEmpty(httpCode) || !httpCode.equals("200")) return null;

                if(!mFilePath.isFile() || !mFilePath.exists() || mFilePath.length() < 1){
                    return null;
                }

                return mFilePath.getAbsolutePath();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值