Autodesk 模型衍生翻译作业导致“TranslationWorker-InternalFailure”响应?

Posted

技术标签:

【中文标题】Autodesk 模型衍生翻译作业导致“TranslationWorker-InternalFailure”响应?【英文标题】:Autodesk model derivative translation job results in `TranslationWorker-InternalFailure` response? 【发布时间】:2018-06-23 16:37:54 【问题描述】:

我正在尝试使用 Autodesk 的 Model Derivative API 将 .zip 文件转换为 .svf 清单。我能够成功创建一个存储桶,使用分块上传将 zip 放入存储桶,并使用相应的端点开始翻译作业(所有端点返回 200)。当我来查看作业的翻译进度时,它卡在“0%完成”,最终返回TranslationWorker-InternalFailure的失败消息。

这一切都是在 Node.js 和 superagent 堆栈上以编程方式完成的,以发出 HTTP 请求。我可以通过使用 Paw 手动翻译来确认文件本身是有效的;并且还通过我们正在替换的旧工具对其进行翻译。

我的代码的具体部分见下文。

Autodesk 翻译工作 (Endpoint)

translate: async function(accessToken, obj) 
    return await request.post('https://developer.api.autodesk.com/modelderivative/v2/designdata/job')
        .set("Authorization", "Bearer " + accessToken)
        .set("Content-Type", "application/json")
        .set('x-ads-force', true)
        .send(
            input: 
                urn: obj.base64Urn,
                compressedUrn: true,
                rootFilename: obj.parentFile
            ,
            output: 
                formats: [
                    
                        type: "thumbnail"
                    ,
                    
                        type: "svf",
                        views: ["2d", "3d"]
                    
                ]
            
        );

在上面的代码中,变量的值如下:

obj.base64Urn 通过以下函数从 Autodesk 提供的 URN 动态转换:

    base64Urn: function() 
        // https://tools.ietf.org/html/rfc7515#appendix-C
        return this.getDataValue("urn") != null ? (new Buffer(this.getDataValue("urn"))).toString('base64').replace(/=+$/g, "").replace(/\+/g, "-").replace(/[\/]/g, "_") : null;
    
obj.parentFile 采用"160728 Small Test Project.rvt" 的形式

Autodesk 翻译进度 (Endpoint)

getTranslationProgressAndDerivatives: function(accessToken, obj) 
    return request.get('https://developer.api.autodesk.com/modelderivative/v2/designdata/' + obj.base64Urn + '/manifest')
        .set('Authorization', "Bearer " + accessToken);

当然,有时必须将 obj 放置在 Autodesk 的服务器上。这是通过这段代码完成的:

Autodesk 将对象放入存储桶 (Endpoint)

class HttpAutodeskPutObjectWriteStream extends stream.Writable 

    /**
     * Constructor sets all the properties for the instance.
     *
     * @param string accessToken - The OAuth2 access token needed for server authentication to engage with Autodesk's API.
     * @param Obj obj
     */
    constructor(accessToken, bucket) 
        super();
        this.accessToken = accessToken;
        this.obj = obj;
        this._bytesTransferred = 0;
        this._putHttpUrl = 'https://developer.api.autodesk.com/oss/v2/buckets/' + this.obj.name + '/objects/' + this.obj.name + '/resumable';
    

    /**
     * Return a bytes transferred statement.
     *
     * @private
     *
     * @param chunk - The chunk currently being transferred.
     *
     * @returns string
     */
    _bytesTransferredStatement(chunk) 
        return `bytes $this._bytesTransferred-$this._bytesTransferred+chunk.byteLength-1/$this.obj.zipFileSize`;
    ;

    /**
     * Writes data to the stream. Note the use of the serialize method in the request.
     *
     * @private
     *
     * @param chunk - The chunk currently being transferred.
     * @param encoding - The encoding of the chunk data.
     * @param callback - The function to be called on chunk completion (success or otherwise).
     *
     * @returns Promise.<void>
     */
    async _write(chunk, encoding, callback) 
        try 
            let stmt = this._bytesTransferredStatement(chunk);
            this._bytesTransferred += chunk.byteLength;

            let response = await request.put(this._putHttpUrl)
                .set("Authorization", "Bearer " + this.accessToken)
                .set("Session-Id", this.bucket.key)
                .set("Content-Length", chunk.byteLength)
                .set("Content-Range", stmt)
                .serialize(function(d)  return d; )
                .send(chunk.toString());

            if (response.status === 200) 
                this.urn = response.body.objectId;
            
            callback(null);

         catch (e) 
            callback(e);
        
    ;

然后在这里调用:

put: function(accessToken, bucketEntity) 
    return new Promise(async (resolve, reject) => 
        const maximalChunkedTransferSize = 2*1024*1024; // 2MB (Minimum amount, Autodesk recommends 5MB).

        const objStorageLocation = (await config.get())[process.env.NODE_ENV].objStorageLocation;
        const pathToFile = path.join(__dirname, "../../", objStorageLocation, obj.name + ".zip");

        let readFileStream = fs.createReadStream(pathToFile,  highWaterMark: maximalChunkedTransferSize );

        let ws = new HttpAutodeskPutObjectWriteStream(accessToken, obj);
        readFileStream.pipe(ws);

        ws.on("finish", () => resolve(ws.urn));
        ws.on("error", () => reject());
    );

当作业失败时...

一旦失败,这是我从翻译进度端点收到的响应:


    "type": "manifest",
    "hasThumbnail": "false",
    "status": "failed",
    "progress": "complete",
    "region": "US",
    "urn": "<redacted>",
    "version": "1.0",
    "derivatives": [
        
            "name": "LMV Bubble",
            "hasThumbnail": "false",
            "status": "failed",
            "progress": "complete",
            "messages": [
                
                    "type": "error",
                    "message": "Translation failure",
                    "code": "TranslationWorker-InternalFailure"
                
            ],
            "outputType": "svf"
        
    ]

我是否在这里做任何明显错误的事情,在尝试翻译文件时会导致 100% 的失败率?

【问题讨论】:

【参考方案1】:

当然,在 *** 上发帖会让您从不同的角度对代码进行心理审查。问题出在我上传文件的过程中,特别是最后一个链接的方法:

let response = await request.put(this._putHttpUrl)
    .set("Authorization", "Bearer " + this.accessToken)
    .set("Session-Id", this.bucket.key)
    .set("Content-Length", chunk.byteLength)
    .set("Content-Range", stmt)
    .serialize(function(d)  return d; )
    .send(chunk.toString()); // HERE

在块上调用.toString()是不正确的。

【讨论】:

以上是关于Autodesk 模型衍生翻译作业导致“TranslationWorker-InternalFailure”响应?的主要内容,如果未能解决你的问题,请参考以下文章

Autodesk forge 模型衍生测试 API

Autodesk Viewer 问题和从翻译到 SVF 的缺失元素

如何将 Autodesk 模型衍生 API 元数据中的 objectids 与 Forge Viewer 模型 dbids 匹配?

如何从 Autodesk 模型衍生 API 的响应中识别提取的 obj 文件?

Autodesk Forge 设计自动化/模型衍生 API - 查看器缓存 svf 文件

SVF POST 作业文件转换失败