• C#二次开发BIMFACE系列68 File Management文件管理服务接口二次开发及实战详解


      在我的博客《C#二次开发BIMFACE系列61 File Management文件管理服务接口二次开发及实战详解》最后列出了 File Management 的接口,本篇主要介绍对该接口的封装及Demo程序。

    本篇内容对应的视频教程《BIMFACE二次开发系列11.2 File Management接口二次开发及实战详解》

    B站:https://www.bilibili.com/video/BV1Ei4y1U7k7

    头条:https://www.ixigua.com/7087537345448116776

    File Management 相关名称解释

      文件管理File Management API由以下基本类型构成,熟悉以下名词,以便更好的理解 File Management 模块

    以上几种存储类型之间存在关联关系,层级关系如下所示:

    • 需要通过Hub导航到Project,每个用户的Project都隶属于某个广联达产品的存储中心(hub);
    • Folder隶属于Project,也可以把Project看做一个根文件夹;
    • FileItem为存储数据的基本单元,可以位于Folder下一层级,也可以和Folder同一层级。
    访问密钥(Access Token)

    Access Token代表了用户当前应用的身份,用户可以通过Access Token对自己应用内的文件发起文件上传、下载、删除、更新等操作,同时也能访问所有BIMFACE的服务端数据接口进行轻量化和数据服务等操作。因此,获取AccessToken是程序开发的第一步,更多关于Access Token的说明可参考Access Token

    错误码

    当用户访问File Management API出现错误时,File Management将返回给用户一个HTTP状态码,错误原因将在响应正文中返回,便于用户定位问题。

    以下是伴随HTTP 404的错误码响应示例。

    复制代码
    {
        "timestamp": 1646985853402,
        "status": 404,
        "error": "Not Found",
        "message": "",
        "path": "/bdfs/v1/projects/10000000006016/folders/10000000006017/parent"
    }
    复制代码
    术语表

    File Management API封装

    在我的开源项目《BIMFACE.SDK.CSharp》中封装了54个File Management 接口的同步与异步方法,如下图

    这里列出几个核心接口的封装代码

    获取Hub列表

     1 /// <summary>
     2 /// 获取Hub列表
     3 /// <para>通过该接口可查询您的账号已注册哪些存储中心(Hub),您可以将文件上传到已注册的存储空间里。</para>
     4 /// </summary>
     5 /// <param name="accessToken">【必填】令牌</param>
     6 /// <param name="dateTimeFrom">【选填】开始时间,筛选时间范围内创建的Hub,格式为:yyyy-MM-dd HH:mm:ss</param>
     7 /// <param name="dateTimeTo">【选填】终止时间,筛选时间范围内创建的Hub,格式为:yyyy-MM-dd HH:mm:ss</param>
     8 /// <param name="info">【选填】描述信息</param>
     9 /// <param name="name">【选填】Hub名称</param>
    10 /// <param name="tenantCode">【选填】产品所属的租户 (默认值:"BIMFACE")</param>
    11 /// <returns></returns>
    12 /// <exception cref="BIMFaceException"></exception>
    13 public virtual HubsResponse GetHubs(string accessToken, string dateTimeFrom = "", string dateTimeTo = "", string info = "", string name = "", string tenantCode = "BIMFACE")
    14 {
    15     /*官方文档:https://bimface.com/docs/file-management/v1/api-reference/getHubListUsingGET.html */
    16 
    17     //GET https://api.bimface.com/bdfs/domain/v1/hubs
    18     string url = BIMFaceConstants.API_HOST + "/bdfs/domain/v1/hubs?1=1";
    19     if (!string.IsNullOrWhiteSpace(dateTimeFrom))
    20     {
    21         url += "&dateTimeFrom=" + dateTimeFrom;
    22     }
    23     if (!string.IsNullOrWhiteSpace(dateTimeTo))
    24     {
    25         url += "&dateTimeTo=" + dateTimeTo;
    26     }
    27     if (!string.IsNullOrWhiteSpace(info))
    28     {
    29         url += "&info=" + info;
    30     }
    31     if (!string.IsNullOrWhiteSpace(name))
    32     {
    33         url += "&name=" + name;
    34     }
    35     if (!string.IsNullOrWhiteSpace(tenantCode))
    36     {
    37         url += "&tenantCode=" + tenantCode;
    38     }
    39 
    40     BIMFaceHttpHeaders headers = new BIMFaceHttpHeaders();
    41     headers.AddOAuth2Header(accessToken);
    42 
    43     try
    44     {
    45         HubsResponse response;
    46 
    47         HttpManager httpManager = new HttpManager(headers);
    48         HttpResult httpResult = httpManager.Get(url);
    49         if (httpResult.Status == HttpResult.STATUS_SUCCESS)
    50         {
    51             response = httpResult.Text.DeserializeJsonToObject<HubsResponse>();
    52         }
    53         else
    54         {
    55             response = new HubsResponse
    56             {
    57                 Message = httpResult.RefText
    58             };
    59         }
    60 
    61         return response;
    62     }
    63     catch (Exception ex)
    64     {
    65         throw new BIMFaceException("[获取Hubs]发生异常!", ex);
    66     }
    67 }
    View Code

    创建项目

     1 /// <summary>
     2 /// 创建项目
     3 /// <para>用Access Token创建项目,对文件分项目进行管理,创建项目之前需要获取应用所属的hubId。</para>
     4 /// </summary>
     5 /// <param name="accessToken">【必填】令牌</param>
     6 /// <param name="hubId">【必填】hub编号</param>
     7 /// <param name="projectName">【必填】项目名称</param>
     8 /// <param name="projectInfo">【选填】项目描述,最多255个字符</param>
     9 /// <param name="projectThumbnail">【选填】项目缩略图url</param>
    10 /// <returns></returns>
    11 /// <exception cref="BIMFaceException"></exception>
    12 public virtual ProjectResponse CreateProject(string accessToken, string hubId, string projectName, string projectInfo = null, string projectThumbnail = null)
    13 {
    14     /*官方文档:https://bimface.com/docs/file-management/v1/api-reference/createProjectUsingPOST.html */
    15 
    16     //POST https://api.bimface.com/bdfs/domain/v1/hubs/{hubId}/projects
    17     string url = string.Format(BIMFaceConstants.API_HOST + "/bdfs/domain/v1/hubs/{0}/projects", hubId);
    18 
    19     string data = new ProjectSaveRequest
    20     {
    21         Name = projectName,
    22         Thumbnail = projectThumbnail,
    23         Info = projectInfo
    24     }.SerializeToJson();
    25 
    26     BIMFaceHttpHeaders headers = new BIMFaceHttpHeaders();
    27     headers.AddOAuth2Header(accessToken);
    28 
    29     try
    30     {
    31         ProjectResponse response;
    32 
    33         HttpManager httpManager = new HttpManager(headers);
    34         HttpResult httpResult = httpManager.Post(url, data);
    35         if (httpResult.Status == HttpResult.STATUS_SUCCESS)
    36         {
    37             response = httpResult.Text.DeserializeJsonToObject<ProjectResponse>();
    38         }
    39         else
    40         {
    41             response = new ProjectResponse
    42             {
    43                 Message = httpResult.RefText
    44             };
    45         }
    46 
    47         return response;
    48     }
    49     catch (Exception ex)
    50     {
    51         throw new BIMFaceException("[创建项目信息]发生异常!", ex);
    52     }
    53 }
    View Code

    指定目录下创建文件夹

     1 /// <summary>
     2 /// 指定目录下创建文件夹
     3 /// <para>在指定的位置创建文件夹,可对文件进行分类管理。需要获取所属的项目Id,以及文件夹所在位置的上层文件Id或文件路径,两个参数必须二选一填入。</para>
     4 /// </summary>
     5 /// <param name="accessToken">【必填】令牌</param>
     6 /// <param name="projectId">【必填】</param>
     7 /// <param name="folderName">【必填】 文件夹名称</param>
     8 /// <param name="parentPath">【必填】父目录文件路径,parentId和parentPath,必须二选一填入</param>
     9 /// <param name="parentId">【必填】父目录文件ID,parentId和parentPath,必须二选一填入</param>
    10 /// <param name="autoRename">【选填】当存在同名文件夹时,是否重命名(默认false,false情况下有同名文件夹则报错)</param>
    11 /// <returns></returns>
    12 /// <exception cref="BIMFaceException"></exception>
    13 public virtual FolderResponse CreateFolder(string accessToken, string projectId, string folderName, string parentPath, string parentId, bool? autoRename = null)
    14 {
    15     /* 官方文档:https://bimface.com/docs/file-management/v1/api-reference/createFolderUsingPOST.html */
    16 
    17     //POST https://api.bimface.com/bdfs/data/v1/projects/{projectId}/folders
    18     string url = string.Format(BIMFaceConstants.API_HOST + "/bdfs/data/v1/projects/{0}/folders", projectId);
    19     string data = new FolderCreateRequest
    20     {
    21         Name = folderName,
    22         ParentPath = parentPath,
    23         ParentId = parentId,
    24         AutoRename = autoRename
    25     }.SerializeToJson();
    26 
    27     BIMFaceHttpHeaders headers = new BIMFaceHttpHeaders();
    28     headers.AddOAuth2Header(accessToken);
    29 
    30     try
    31     {
    32         FolderResponse response;
    33 
    34         HttpManager httpManager = new HttpManager(headers);
    35         HttpResult httpResult = httpManager.Post(url,data);
    36         if (httpResult.Status == HttpResult.STATUS_SUCCESS)
    37         {
    38             response = httpResult.Text.DeserializeJsonToObject<FolderResponse>();
    39         }
    40         else
    41         {
    42             response = new FolderResponse
    43             {
    44                 Message = httpResult.RefText
    45             };
    46         }
    47 
    48         return response;
    49     }
    50     catch (Exception ex)
    51     {
    52         throw new BIMFaceException("[创建文件夹信息]发生异常!", ex);
    53     }
    54 }
    View Code

    上传文件(普通文件流方式)

     1 /// <summary>
     2 ///  普通文件流上传文件【使用BIMFACE公有云时不推荐使用该方式。推荐使用文件直传 UploadFileByPolicy()方法,效率更高】。
     3 /// <para>使用普通文件流上传,文件流需要在request body中传递。</para>
     4 /// </summary>
     5 /// <param name="accessToken">【必填】令牌</param>
     6 /// <param name="projectId">【必填】项目ID</param>
     7 /// <param name="fileName">【必填】文件的名称(不包含路径)</param>
     8 /// <param name="fileStream">【必填】文件流</param>
     9 /// <param name="parentId">【必填】父文件夹Id,parentId和parentPath必须二选一填入</param>
    10 /// <param name="parentPath">【必填】父文件夹路径,parentId和parentPath必须二选一填入</param>
    11 /// <param name="autoRename">【可选】当存在同名文件时,是否自动重命名,默认为false </param>
    12 /// <param name="sourceId">【可选】调用方的文件源ID,不能重复</param>
    13 /// <returns></returns>
    14 public virtual FileUpload2Response UploadFileByStream(string accessToken, string projectId, string fileName, Stream fileStream, string parentId, string parentPath, bool? autoRename = null, string sourceId = "")
    15 {
    16     /* 官方文档:https://bimface.com/docs/file-management/v1/api-reference/uploadFileItemUsingPOST.html */
    17 
    18     /* 此API详解,参考作者博客:《C#开发BIMFACE系列4 服务端API之源上传文件》 https://www.cnblogs.com/SavionZhang/p/11425804.html */
    19 
    20     /* 重要提示:使用普通文件流上传,不支持表单方式; 文件流需要在 request body 中传递 */
    21 
    22     byte[] fileBytes = fileStream.ToByteArray();
    23 
    24     //POST https://api.bimface.com/bdfs/data/v1/projects/{projectId}/fileItems
    25     string url = string.Format(BIMFaceConstants.API_HOST + "/bdfs/data/v1/projects/{0}/fileItems", projectId);
    26     url = url + "?name=" + fileName.UrlEncode(Encoding.UTF8); // 使用URL编码(UTF-8)
    27     if (!string.IsNullOrEmpty(parentId))
    28     {
    29         url = url + "&parentId=" + parentId;
    30     }
    31     if (!string.IsNullOrEmpty(parentPath))
    32     {
    33         url = url + "&parentPath=" + parentPath;
    34     }
    35 
    36     url = url + "&length=" + fileBytes.Length;
    37 
    38     if (autoRename.HasValue)
    39     {
    40         url = url + "&autoRename=" + autoRename.Value;
    41     }
    42     if (!string.IsNullOrEmpty(sourceId))
    43     {
    44         url = url + "&sourceId=" + sourceId;
    45     }
    46 
    47     BIMFaceHttpHeaders headers = new BIMFaceHttpHeaders();
    48     headers.AddOAuth2Header(accessToken);
    49 
    50     try
    51     {
    52         FileUpload2Response response;
    53 
    54         HttpManager httpManager = new HttpManager(headers);
    55         HttpResult httpResult = httpManager.UploadData(url, fileBytes, WebRequestMethods.Http.Post);
    56         if (httpResult.Status == HttpResult.STATUS_SUCCESS)
    57         {
    58             response = httpResult.Text.DeserializeJsonToObject<FileUpload2Response>();
    59         }
    60         else
    61         {
    62             response = new FileUpload2Response
    63             {
    64                 Message = httpResult.RefText
    65             };
    66         }
    67 
    68         return response;
    69     }
    70     catch (Exception ex)
    71     {
    72         throw new BIMFaceException("[普通文件流上传文件]发生异常!", ex);
    73     }
    74 }
    View Code

    上传文件(外部文件url方式)

     1 /// <summary>
     2 ///  指定外部文件url方式上传文件。
     3 /// <para>如果需要上传的文件不在本地,且该文件可以通过指定的HTTP URL可以下载,BIMFACE支持直接传一个外部的HTTP文件URL,BIMFACE会去下载该文件,而无须用户先下载再上传。</para>
     4 /// </summary>
     5 /// <param name="accessToken">【必填】令牌</param>
     6 /// <param name="projectId">【必填】项目ID</param>
     7 /// <param name="fileName">【必填】文件的名称(不包含路径)</param>
     8 /// <param name="parentId">【必填】父文件夹Id,parentId和parentPath必须二选一填入</param>
     9 /// <param name="parentPath">【必填】父文件夹路径,parentId和parentPath必须二选一填入</param>
    10 /// <param name="fileUrl">【必填】外部文件的url地址</param>
    11 /// <param name="autoRename">【可选】当存在同名文件时,是否自动重命名,默认为false </param>
    12 /// <param name="sourceId">【可选】调用方的文件源ID,不能重复</param>
    13 /// <param name="etag">【可选】文件etag</param>
    14 /// <param name="maxLength">【可选】</param>
    15 /// <returns></returns>
    16 public virtual FileUpload2Response UploadFileByUrl(string accessToken, string projectId, string fileName, string parentId, string parentPath, string fileUrl, bool? autoRename = null, string sourceId = "", string etag = "", long? maxLength = null)
    17 {
    18     /* 官方文档:https://bimface.com/docs/file-management/v1/api-reference/uploadByUrlUsingPOST.html */
    19 
    20     /* 此API详解,参考作者博客:《C#开发BIMFACE系列4 服务端API之源上传文件》 https://www.cnblogs.com/SavionZhang/p/11425804.html */
    21 
    22     /* 如果需要上传的文件不在本地,且该文件可以通过指定的HTTP URL可以下载,BIMFACE支持直接传一个外部的HTTP文件URL, BIMFACE会去下载该文件,而无须用户先下载,再上传。 */
    23 
    24     //POST https://api.bimface.com/bdfs/data/v1/projects/{projectId}/fileItems/sourceUrl
    25     string url = string.Format(BIMFaceConstants.API_HOST + "/bdfs/data/v1/projects/{0}/fileItems/sourceUrl", projectId);
    26     url = url + "?name=" + fileName.UrlEncode(Encoding.UTF8); // 使用URL编码(UTF-8)
    27 
    28     if (!string.IsNullOrWhiteSpace(parentId))
    29     {
    30         url = url + "&parentId=" + parentId;
    31     }
    32     if (!string.IsNullOrWhiteSpace(parentPath))
    33     {
    34         url = url + "&parentPath=" + parentPath;
    35     }
    36 
    37     url = url + "&url=" + fileUrl.UriEscapeDataString();
    38 
    39     if (autoRename.HasValue)
    40     {
    41         url = url + "&autoRename=" + autoRename.Value;
    42     }
    43     if (!string.IsNullOrWhiteSpace(etag))
    44     {
    45         url = url + "&etag=" + etag;
    46     }
    47     if (maxLength.HasValue)
    48     {
    49         url = url + "&maxLength=" + maxLength.Value;
    50     }
    51     if (!string.IsNullOrWhiteSpace(sourceId))
    52     {
    53         url = url + "&sourceId=" + sourceId;
    54     }
    55 
    56     BIMFaceHttpHeaders headers = new BIMFaceHttpHeaders();
    57     headers.AddOAuth2Header(accessToken);
    58 
    59     try
    60     {
    61         FileUpload2Response response;
    62 
    63         HttpManager httpManager = new HttpManager(headers);
    64         HttpResult httpResult = httpManager.Post(url);
    65         if (httpResult.Status == HttpResult.STATUS_SUCCESS)
    66         {
    67             response = httpResult.Text.DeserializeJsonToObject<FileUpload2Response>();
    68         }
    69         else
    70         {
    71             response = new FileUpload2Response
    72             {
    73                 Message = httpResult.RefText
    74             };
    75         }
    76 
    77         return response;
    78     }
    79     catch (Exception ex)
    80     {
    81         throw new BIMFaceException("[指定外部文件url方式上传文件]发生异常!", ex);
    82     }
    83 }
    View Code

    上传文件(文件直传)

     1 /// <summary>
     2 ///  【推荐使用该方式】根据policy凭证在web端上传文件。
     3 /// <para>通过接口获取文件直传的policy凭证后,可以直接在前端使用表单上传方式将文件上传到BIMFACE的对象存储上。</para>
     4 /// <para>特别提醒:BIMFACE公有云支持文件直传。私有化部署时使用的对象存储是 MinIO,不支持 Policy 上传。使用普通文件流上传 或者 指定外部文件URL方式上传。</para>
     5 /// </summary>
     6 /// <param name="accessToken">【必填】令牌</param>
     7 ///  <param name="projectId">【必填】项目ID</param>
     8 /// <param name="fileFullName">【必填】待上传的文件(包含全路径的完全限定名)</param>
     9 /// <param name="parentId">【必填】父文件夹Id,parentId和parentPath必须二选一填入</param>
    10 /// <param name="parentPath">【必填】父文件夹路径,parentId和parentPath必须二选一填入</param>
    11 /// <param name="autoRename">【可选】当存在同名文件时,是否自动重命名,默认为false </param>
    12 /// <param name="sourceId">【可选】调用方的文件源ID,不能重复</param>
    13 /// <param name="maxLength">【可选】</param>
    14 /// <returns></returns>
    15 public virtual FileUpload2Response UploadFileByPolicy(string accessToken, string projectId, string fileFullName, string parentId, string parentPath, bool? autoRename = null, string sourceId = "", long? maxLength = null)
    16 {
    17     /* 官方文档:https://bimface.com/docs/file-management/v1/api-reference/uploadByPolicyUsingPOST.html */
    18     /* 此API详解,参考作者博客:《C#开发BIMFACE系列5 服务端API之文件直传》 https://www.cnblogs.com/SavionZhang/p/11425945.html */
    19 
    20     /* BIMFACE使用了分布式对象存储来存储用户上传的模型/图纸文件。
    21        如使用普通的文件上传接口,文件流会通过BIMFACE的服务器,再流向最终的分布式存储系统,整个上传过程会受BIMFACE服务器的带宽限制,上传速度非最优。 
    22        如使用文件直传接口,开发者应用在申请到一个Policy凭证后,可以直接上传文件跟BIMFACE后台的分布式存储系统, 
    23        这样上传速度和稳定性都会有提升,是我们推荐的上传方式。 
    24     */
    25 
    26     /* 使用流程如下:
    27         1、开发者应用向BIMFACE申请上传Policy请求。
    28         2、BIMFACE返回上传Policy和签名给开发者应用。
    29         3、开发者应用使用在第二个步骤中获取的URL信息,直接上传文件数据到BIMFACE后端的分布式对象存储。
    30      */
    31 
    32     FileUpload2Response response = null;
    33     try
    34     {
    35         string fileName = new FileInfo(fileFullName).Name;
    36 
    37         FileUploadPolicyResponse policyResponse = GetFileUploadPolicy(accessToken, projectId, fileName, parentId, parentPath, autoRename, sourceId, maxLength);
    38         if (policyResponse.Code == HttpResult.STATUS_SUCCESS)
    39         {
    40             /* 官方文档 https://bimface.com/docs/file-management/v1/api-reference/getFilePolicyUsingGET.html
    41              * 中说明该接口的请求地址为:POST https://api.bimface.com/bdfs/data/v1/projects/policy
    42              *
    43              *  经测试
    44              * (1)使用该地址在postman中测试可以成功。但是使用本程序测试失败,提示 unauthorized。Full authentication is required to access this resource。
    45              * (2)使用“获取文件直传的policy凭证”接口中返回的 host 地址(https://bf-prod-srcfile.oss-cn-beijing.aliyuncs.com),本程序测试成功。
    46              */
    47 
    48             //string url = BIMFaceConstants.API_HOST + "/bdfs/data/v1/projects/policy";
    49             string url = policyResponse.Data.Host;
    50 
    51             /* C# 语言 Dictionary 字典中 key 是关键字,不能添加进去。所以统一添加了响应的后缀 _BIMFACE_,解析时再去除后缀 */
    52             NameValueCollection kVDatas = new NameValueCollection();
    53             kVDatas.Add("name" + StringUtils.Symbol.KEY_SUFFIX, fileName);
    54             kVDatas.Add("key" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.ObjectKey);
    55             kVDatas.Add("policy" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.Policy);
    56             kVDatas.Add("OSSAccessKeyId" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.AccessId);
    57             kVDatas.Add("success_action_status" + StringUtils.Symbol.KEY_SUFFIX, "200");
    58             kVDatas.Add("callback" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.CallbackBody);
    59             kVDatas.Add("signature" + StringUtils.Symbol.KEY_SUFFIX, policyResponse.Data.Signature);
    60 
    61             BIMFaceHttpHeaders headers = new BIMFaceHttpHeaders();
    62             headers.AddOAuth2Header(accessToken);
    63 
    64             HttpManager httpManager = new HttpManager(headers);
    65             HttpResult httpResult = httpManager.UploadFormByMultipart(url, fileFullName, kVDatas);
    66             if (httpResult.Status == HttpResult.STATUS_SUCCESS)
    67             {
    68                 response = httpResult.Text.DeserializeJsonToObject<FileUpload2Response>();
    69             }
    70             else
    71             {
    72                 response = new FileUpload2Response
    73                 {
    74                     Message = httpResult.RefText
    75                 };
    76             }
    77         }
    78 
    79         return response;
    80     }
    81     catch (Exception ex)
    82     {
    83         throw new BIMFaceException("[通过文件直传的policy凭证,直接上传文件时]发生异常!", ex);
    84     }
    85 }
    View Code

    其他接口封装,请下载《BIMFACE.SDK.CSharp》进行阅读。

    Demo程序

    运行效果如下:

    测试
    • 获取Hubs列表

    • 获取Projects列表

    • 创建项目

    • 获取项目信息

    其他接口,请下载《BIMFACE.SDK.CSharp》进行体验。

    接口使用注意事项
    • 上传文件的大小

        通过直流上传、表单上传、追加上传的方式上传单个文件,文件的大小不能超过5 GB。

    • 上传文件格式

        目前支持的文件格式有50+种二维及三维格式,覆盖建筑、化工、机械、能源等行业。

    • 默认项目的默认文件夹无法修改和删除
    • 文件命名

        文件上传前,请确认文件名称中不包含特殊字符 / \n * <> | " : ?,否则文件无法上传成功。

    • 同名文件创建

        默认情况下,如果上传的文件与已有文件同名,无法创建成功并给出错误提示。如果希望创建同名文件,您可以在上传请求的Header中携带参数autoRename,并指定其值为true。

    • 接口参数

        当接口请求参数中同时存在文件Id和文件Path时,请选择其中一个参数填写;若您同时填写,且两个参数指向的文件不同时,Id优先级高于Path。

    • 存储容量

        单个存储空间的容量不限制。

     

  • 相关阅读:
    Vue48-ref属性
    贪吃蛇(C语言版)
    深度强化学习(Deep Reinforcement Learning, DRL)阶段性学习汇总(二)
    Aptos 深度解读:机遇、挑战与风险
    深度学习与CV教程(12) | 目标检测 (两阶段,R-CNN系列)
    什么是 Infamous Skullz NFT 系列?
    【资损】资损防控的系统规范-收单类服务设计
    如何结合phpstorm配置在docker中的xdebug
    uniapp 解决请求出现 /sockjs-node/info?t=问题
    1、SpringCloud大型企业分布式微服务云架构之Markdown 教程
  • 原文地址:https://www.cnblogs.com/SavionZhang/p/16152249.html