大疆上云API源码解析(媒体管理)

文章讲述了Pilot2和机场应用中文件上传的过程,涉及文件指纹的概念、如何确认文件已存在、获取临时上传凭证以及自动与手动上传策略。重点在于文件上传后的回调通知机制,确保上传状态同步到前端。
摘要由CSDN通过智能技术生成

问题

  • [ 精简指纹的作用,一直没理解]
  • [为什么pilot2 上传文件的成功回调不用通知前端已上传数量]

基本概念

文件指纹:文件指纹是指文件的MD5值,是文件打包后输出的文件名的后缀。文件指纹在软件开发、版本控制和网络安全等领域都发挥着重要作用,确保文件的正确性和完整性。

功能概述

Pilot 2或者大疆机场把飞行器上的媒体文件下载到遥控器/机场的本地存储,然后通过网络上传到第三方服务器,媒体上传包含自动上传和手动上传功能

  1. 文件快传 : /media/api/v1/workspaces/{workspace_id}/fast-upload
    传输文件时可能会存在云端已有文件,那么在Pilot2或机场上传文件时,会启动文件快传接口,如果已存在,直接返回上传成功
    @Override
    public HttpResultResponse mediaFastUpload(String workspaceId, @Valid MediaFastUploadRequest request, HttpServletRequest req, HttpServletResponse rsp) {
    	// 根据文件指纹 查询数据库是否存在该文件
        boolean isExist = mediaService.fastUpload(workspaceId, request.getFingerprint());
    
        return isExist ? HttpResultResponse.success() : HttpResultResponse.error(request.getFingerprint() + "don't exist.");
    }
    
  2. 获取已存在文件的精简指纹:/media/api/v1/workspaces/{workspace_id}/files/tiny-fingerprints
    通过精简指纹校验,确认文件是否已经上传
  @Override
    public HttpResultResponse<GetFileFingerprintResponse> getExistFileTinyFingerprint(String workspaceId, @Valid GetFileFingerprintRequest request, HttpServletRequest req, HttpServletResponse rsp) {
        List<String> existingList = mediaService.getExistTinyFingerprints(workspaceId, request.getTinyFingerprints());
        return HttpResultResponse.success(new GetFileFingerprintResponse().setTinyFingerprints(existingList));
    }
  1. 获取上传临时凭证:
    Pilot2: /storage/api/v1/workspaces/{workspace_id}/sts
    每次媒体上传时,需要向服务端获取临时文件上传凭证,这样DJI Pilot 2在上传时会带上该凭证给对象存储服务进行校验。
@Override
    public HttpResultResponse<StsCredentialsResponse> getTemporaryCredential(String workspaceId, HttpServletRequest req, HttpServletResponse rsp) {
        StsCredentialsResponse stsCredentials = storageService.getSTSCredentials();
        return HttpResultResponse.success(stsCredentials);
    }
    // 根据不同的provider 获取不同的临时凭证
    @Override
public StsCredentialsResponse getSTSCredentials() {
    return new StsCredentialsResponse()
        .setEndpoint(OssConfiguration.endpoint)
        .setBucket(OssConfiguration.bucket)
        // 调用具体的对象存储类获取临时凭证信息
        .setCredentials(ossService.getCredentials())
        .setProvider(OssConfiguration.provider)
        .setObjectKeyPrefix(OssConfiguration.objectDirPrefix)
        .setRegion(OssConfiguration.region);
}

机场:通过 thing/product/{gateway_sn}/requests 主题,method:storage_config_get的mqtt消息,请求云端获取上传临时凭证。
method:storage_config_get的mqtt消息对应的实体类为:StorageConfigGet。将消息序列化为实体类后,再根据消息中的method属性,将requests请求消息路由到不同的管道中,method:storage_config_get的mqtt消息路由的管道为ChannelName.INBOUND_REQUESTS_STORAGE_CONFIG_GET

@ServiceActivator(inputChannel = ChannelName.INBOUND_REQUESTS_STORAGE_CONFIG_GET, outputChannel = ChannelName.OUTBOUND_REQUESTS)
    public TopicRequestsResponse<MqttReply<StsCredentialsResponse>> storageConfigGet(TopicRequestsRequest<StorageConfigGet> request, MessageHeaders headers) {
        throw new UnsupportedOperationException("storageConfigGet not implemented");
    }
    @Override
    public TopicRequestsResponse<MqttReply<StsCredentialsResponse>> storageConfigGet(TopicRequestsRequest<StorageConfigGet> response, MessageHeaders headers) {
        return new TopicRequestsResponse<MqttReply<StsCredentialsResponse>>().setData(MqttReply.success(getSTSCredentials()));
    }
 @Override
    public StsCredentialsResponse getSTSCredentials() {
        return new StsCredentialsResponse()
                .setEndpoint(OssConfiguration.endpoint)
                .setBucket(OssConfiguration.bucket)
                .setCredentials(ossService.getCredentials())
                .setProvider(OssConfiguration.provider)
                .setObjectKeyPrefix(OssConfiguration.objectDirPrefix)
                .setRegion(OssConfiguration.region);
    }

  1. 媒体文件上传
    Pilot2或者机场获取到临时凭证信息后,满足不同条件下,会自动将媒体文件上传到指定的对象存储中。
    Pilot2需要满足以下条件之一:

    Pilot2设置了媒体文件自动上传,Pilot2中检测到媒体文件后即自动上传
    Pilot2设置媒体文件手动上传,需要用户在Pilot2的媒体模块手动将媒体文件上传到对象存储中。
    

机场需要在执行完任务后,且无人机生成了媒体文件后,机场自动将媒体文件上传到云端。
5. 文件组上传完成后回调
Pilot2 :/media/api/v1/workspaces/{workspace_id}/upload-callback

@Override
   public HttpResultResponse<String> mediaUploadCallback(String workspaceId, @Valid MediaUploadCallbackRequest request, HttpServletRequest req, HttpServletResponse rsp) {
   // 将结果写入数据库中
       mediaService.saveMediaFile(workspaceId, request);
       return HttpResultResponse.success(request.getObjectKey());
   }

机场:通过 thing/product/{gateway_sn}/events 主题,method:file_upload_callback的mqtt消息:
method:file_upload_callback的mqtt消息对应的实体类为:FileUploadCallback。将消息序列化为实体类后,再根据消息中的method属性,将requests请求消息路由到不同的管道中,method:file_upload_callback的mqtt消息路由的管道为ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK

 @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK, outputChannel = ChannelName.OUTBOUND_EVENTS)
    public TopicEventsResponse<MqttReply> fileUploadCallback(TopicEventsRequest<FileUploadCallback> request, MessageHeaders headers) {
        throw new UnsupportedOperationException("fileUploadCallback not implemented");
    }
@Override
    public TopicEventsResponse<MqttReply> fileUploadCallback(TopicEventsRequest<FileUploadCallback> request, MessageHeaders headers) {
        FileUploadCallback callback = request.getData();

        if (MqttReply.CODE_SUCCESS != callback.getResult()) {
            log.error("Media file upload failed!");
            return null;
        }
		// 获取任务id
        String jobId = callback.getFile().getExt().getFlightId();

        Optional<DeviceDTO> deviceOpt = deviceRedisService.getDeviceOnline(request.getGateway());
        MediaFileCountDTO mediaFileCount = mediaRedisService.getMediaCount(request.getGateway(), jobId);
        // 重复数据
        if (deviceOpt.isEmpty()
                || (Objects.nonNull(mediaFileCount) && request.getBid().equals(mediaFileCount.getBid())
                && request.getTid().equals(mediaFileCount.getTid()))) {
            return new TopicEventsResponse<MqttReply>().setData(MqttReply.success());
        }

        DeviceDTO device = deviceOpt.get();
        // 保存文件到数据库中
        boolean isSave = parseMediaFile(callback, device);
        if (!isSave) {
            log.error("Failed to save the file to the database, please check the data manually.");
            return null;
        }
		// 更新并通知已上传文件数量
        notifyUploadedCount(mediaFileCount, request, jobId, device);
        return new TopicEventsResponse<MqttReply>().setData(MqttReply.success());
    }
  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值