SView Help Center
English (US)

同步文件元信息

Author: sviewngts Last Updated: 2026-08-25 16:31
开启 autoUpgrade 后,命中同名文件时将自动将同名文件迭代升级为新版本
接口名 POST: /login-register/open-api/documents/sync-file-meta
入参:(body传值) application/json
是否必传 默认值 描述 备注
fileMd5 是 - 文件MD5 文件MD5
fileSize 是 - 文件大小,单位字节  
originalFilename 是 - 原始文件名(例:'模型.prt') 页面中展示的文件名
fileName 是 - 真实文件名(例:'uuid.prt') 实际物理文件的文件名,用于文件存储,不能包含下列任何字符:\ / : * ? " < > |
dir 是 - 相对路径 获取图文档上传链接接口返回的relativePath值
pfolderId 否 "0" 所属文件夹ID
"0"代表根目录
所属文件夹ID,需提前创建父文件夹 为空时默认是"0"
autoUpgrade 否 "n" 是否开启自动版本升级 是->y
否->n
fileScope 是 - 文件归属域 我的空间->personal 
项目空间(企业空间)->project
projectCode 否 - 该项目在外部平台的唯一编码,需提前创建项目 fileScope 为 project 时需要传递
入参:(Header传值)
Authorization 是 - 传递AccessToken 格式:Bearer {AccessToken}
入参示例:(application/json)

 

{
    "fileId": "",
    "fileMd5": "17fc1899dexxx9c24850d308a9",
    "fileSize": 72635,
    "originalFilename": "test.prt",
    "fileName": "test.prt",
    "dir": "sviewbusiness%2Ftest%2F20260526%2F105840196370411d9a70af13d98a45ed%2Ftest.prt",
    "pfolderCode": "PROJ_001",
    "autoUpgrade": "y",
    "fileScope":"personal"
}
回参示例:(application/json)

 

{
    "code": 0,
    "msg": null,
    "data": {
    "bucketName": "sviewngts",
    "path": "sviewbusiness%2Ftest%2F20260526%2F105840196370411d9a70af13d98a45ed%2Ftest.prt",
    "fileName": "test.prt",
    "url": "/personal/space/download/7da327f74exxxx18d4ff661ac3e2830",
    "fileId": "7da327f74exxxx18d4ff661ac3e2830",
    "upgraded": true,
    "revisionNumber": "V2",
    "itemId": "7da327f74exxxx18d4fffdfdac3e2830"
    },
    "ok": true
}
package com.hoteam.sview.demo;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hoteam.sview.ngts.loginRegister.vo.OpenApiSyncFileMetaVO;
import lombok.extern.slf4j.Slf4j;

import java.io.File;

/**
 * OpenAPI - 同步文件元信息(自动升版) 调用Demo
 * <p>
 * 接口地址:POST /login-register/open-api/documents/sync-file-meta
 * 鉴权:Header Authorization: Bearer {AccessToken}
 * 调用时机:文件通过上传链接PUT上传完成后,同步文件元信息落库;支持同名文件自动迭代升版
 * 字段说明:
 * fileScope=personal(我的空间)无需传projectId;fileScope=project(项目空间)必须传入projectId
 * autoUpgrade=y 开启同名文件自动版本迭代;n关闭,默认n
 */
@Slf4j
public class SyncFileMetaOpenApiDemo {

    // 网关域名,部署替换为真实地址
    private static final String API_URL = "http://your-gateway-host/login-register/open-api/documents/sync-file-meta";

    // 上传状态常量
    public static final String UPLOAD_STATUS_SUCCESS = "0";
    public static final String UPLOAD_STATUS_FAIL = "1";
    // 自动升版标识
    public static final String AUTO_UPGRADE_ON = "y";
    public static final String AUTO_UPGRADE_OFF = "n";
    // 文件归属域
    public static final String SCOPE_PERSONAL = "personal";
    public static final String SCOPE_PROJECT = "project";

    /**
     * 同步文件元信息通用方法
     *
     * @param accessToken      OAuth2获取的访问凭证
     * @param fileMd5          文件MD5(必填)
     * @param fileSize         文件字节大小(必填)
     * @param originalFilename 页面展示文件名(必填)
     * @param fileName         OSS真实存储文件名(必填,禁止包含\/:*?"<>|)
     * @param dir              上传链接接口返回的relativePath(必填)
     * @param pfolderId        父文件夹ID,不传默认0(根目录)
     * @param projectCode      该项目在外部平台的唯一编码,fileScope=project时必传
     * @param autoUpgrade      是否自动升版 y/n,默认n
     * @param fileScope        personal=我的空间 / project=项目空间(必填)
     * @param uploadStatus     上传状态 0成功/1失败
     * @return 同步结果VO,失败返回null
     */
    public static OpenApiSyncFileMetaVO syncFileMeta(String accessToken,
                                                     String fileMd5,
                                                     long fileSize,
                                                     String originalFilename,
                                                     String fileName,
                                                     String dir,
                                                     String pfolderId,
                                                     String projectCode,
                                                     String autoUpgrade,
                                                     String fileScope,
                                                     String uploadStatus) {
        // 基础入参校验
        if (StrUtil.isBlank(accessToken)) {
            log.warn("accessToken 不能为空");
            return null;
        }
        if (StrUtil.hasBlank(fileMd5, originalFilename, fileName, dir, fileScope, uploadStatus)) {
            log.warn("必填参数缺失:fileMd5/originalFilename/fileName/dir/fileScope/uploadStatus 不能为空");
            return null;
        }
        if (fileSize <= 0) {
            log.warn("文件大小必须大于0,当前size:{}", fileSize);
            return null;
        }
        // 校验文件名非法字符
        if (StrUtil.containsAny(fileName, "\\", "/", ":", "*", "?", "\"", "<", ">", "|")) {
            log.warn("真实文件名包含非法字符 fileName:{}", fileName);
            return null;
        }
        // 项目空间强制校验projectId
        if (SCOPE_PROJECT.equals(fileScope) && StrUtil.isBlank(projectCode)) {
            log.warn("fileScope为project时,projectCode不能为空");
            return null;
        }

        // 组装请求Body
        JSONObject body = new JSONObject();
        body.set("fileMd5", fileMd5);
        body.set("fileSize", fileSize);
        body.set("originalFilename", originalFilename);
        body.set("fileName", fileName);
        body.set("dir", dir);
        body.set("pfolderId", StrUtil.isBlank(pfolderId) ? "0" : pfolderId);
        body.set("uploadStatus", uploadStatus);
        body.set("fileScope", fileScope);
        body.set("autoUpgrade", StrUtil.isBlank(autoUpgrade) ? AUTO_UPGRADE_OFF : autoUpgrade);
        // 项目ID仅非空时塞入
        if (StrUtil.isNotBlank(projectId)) {
            body.set("projectCode", projectCode);
        }

        // 构建请求
        HttpRequest request = HttpRequest.post(API_URL)
                .header(Header.AUTHORIZATION, "Bearer " + accessToken)
                .header(Header.CONTENT_TYPE, ContentType.JSON.getValue())
                .body(body.toString())
                .timeout(10_000);
        // 注入公共请求头(租户、设备、语言等)
        CommonHeaderUtil.withCommonHeaders(request);

        try (HttpResponse response = request.execute()) {
            int httpCode = response.getStatus();
            String respBody = response.body();
            log.info("同步文件元信息接口响应 httpCode:{}, body:{}", httpCode, respBody);

            // 401鉴权失败
            if (httpCode == HttpStatus.HTTP_UNAUTHORIZED) {
                log.warn("AccessToken失效或无权限,响应:{}", respBody);
                return null;
            }
            // HTTP非200判定异常
            if (!response.isOk() || StrUtil.isBlank(respBody)) {
                log.warn("接口请求异常 httpCode:{} body:{}", httpCode, respBody);
                return null;
            }

            JSONObject respJson = JSONUtil.parseObj(respBody);
            // 业务码code=0代表成功
            Integer code = respJson.getInt("code");
            if (code == null || code != 0) {
                log.warn("业务处理失败 code:{}, msg:{}, fullBody:{}", code, respJson.getStr("msg"), respBody);
                return null;
            }

            // 解析data为返回VO
            JSONObject data = respJson.getJSONObject("data");
            if (data == null) {
                log.warn("响应data为空 body:{}", respBody);
                return null;
            }
            OpenApiSyncFileMetaVO vo = JSONUtil.toBean(data, OpenApiSyncFileMetaVO.class);
            log.info("文件元信息同步成功 fileId:{} 是否升版:{} 版本号:{}",
                    vo.getFileId(), vo.getUpgraded(), vo.getRevisionNumber());
            return vo;
        } catch (Exception e) {
            log.error("同步文件元信息请求发生异常", e);
            return null;
        }
    }

    public static void main(String[] args) {
        // 1. 获取登录凭证
        String accessToken = OAuth2TokenIntegrationDemo.getAccessTokenByIntegration("18377xxxxxxx69049");
        // 2. 本地待上传文件
        File localFile = new File("D:/model/test.prt");
        String originalFileName = "设备模型.prt";
        String realFileName = SecureUtil.md5(localFile) + ".prt";
        long fileSize = localFile.length();
        String fileMd5 = SecureUtil.md5(localFile);
        // 3. 前置:调用获取上传链接接口拿到relativePath
        GetUploadUrlDemo.UploadUrlResult uploadUrlResult = GetUploadUrlDemo.getUploadUrl(realFileName, GetUploadUrlDemo.Category.ENT_MY_SPACE);
        if (uploadUrlResult == null) {
            log.error("获取上传链接失败,终止流程");
            return;
        }
        // 4. 前置:PUT上传文件至OSS
        boolean uploadSuccess = LocalUploadDemo.uploadByUploadUrl(uploadUrlResult.getUploadUrl(), localFile);
        if (!uploadSuccess) {
            log.error("文件OSS上传失败,终止流程");
            return;
        }

        // ====================== 场景1:我的空间(personal,无需projectId,关闭自动升版)======================
        OpenApiSyncFileMetaVO personalResult = syncFileMeta(
                accessToken,
                fileMd5,
                fileSize,
                originalFileName,
                realFileName,
                uploadUrlResult.getRelativePath(),
                "0", // 根目录
                null,
                AUTO_UPGRADE_OFF,
                SCOPE_PERSONAL,
                UPLOAD_STATUS_SUCCESS
        );
        if (personalResult != null) {
            log.info("我的空间文件同步完成 fileId:{} 下载地址:{}", personalResult.getFileId(), personalResult.getUrl());
        }

        // ====================== 场景2:项目空间(project,传projectId,开启自动升版)======================
        String targetProjectId = "proj_00123456789";
        OpenApiSyncFileMetaVO projectResult = syncFileMeta(
                accessToken,
                fileMd5,
                fileSize,
                originalFileName,
                realFileName,
                uploadUrlResult.getRelativePath(),
                "folder_666",
                projectCode,
                AUTO_UPGRADE_ON,
                SCOPE_PROJECT,
                UPLOAD_STATUS_SUCCESS
        );
        if (projectResult != null) {
            log.info("项目空间文件同步完成 fileId:{} 已升版:{} 新版本号:{}",
                    projectResult.getFileId(), projectResult.getUpgraded(), projectResult.getRevisionNumber());
        }
    }
}