用于嵌入图像的 VersionOne API 返回 404未找到

问题描述

我正在尝试编写一个工具(在 C# 中)从 VersionOne 资产(故事/缺陷)中读取嵌入的图像并将它们存储在本地(以便以后能够将它们迁移到另一个地方)。

我找到了这个链接以供参考: https://community.versionone.com/Digital.ai_Agility_Integrations/Developer_Library/Get_an_SDK/.NET_SDK/Working_with_Attachments_and_Images

这样我就可以成功读取附件,但是嵌入的图像仍然是一个问题。

我目前对此的尝试是这样的:

        public string StoreActiveV1ItemEmbeddedImages(PrimaryWorkitem v1Item,string targetPath,out int countStored)
    {
        string result = string.Empty;
        countStored = 0;
        if (v1Item == null) return "Error: No V1 item given to StoreActiveV1ItemEmbeddedImages!";
        string filePath = targetPath;
        if (!filePath.EndsWith("\\")) filePath += "\\";
        if (!Directory.Exists(filePath)) return "Error: Given path '" + filePath + "' does not exist!";
        IServices services = v1Instance.apiclient.Services;
        Imetamodel metamodel = v1Instance.apiclient.metamodel;
        IAttachments attachments = v1Instance.apiclient.Attachments;
        Oid itemOid = services.Getoid(v1Item.ID.Token); 
        IAssetType assetType = metamodel.GetAssetType("EmbeddedImage");
        var query = new Query(assetType);
        IAttributeDeFinition contentAttribute = assetType.GetAttributeDeFinition("Content");
        IAttributeDeFinition contentTypeAttribute = assetType.GetAttributeDeFinition("ContentType");
        IAttributeDeFinition assetAttribute = assetType.GetAttributeDeFinition("Asset");
        query.Selection.Add(contentAttribute);
        query.Selection.Add(contentTypeAttribute);
        query.Selection.Add(assetAttribute);
        FilterTerm term = new FilterTerm(assetAttribute);
        term.Equal(itemOid.Momentless);
        query.Filter = term;
        QueryResult queryResult = services.Retrieve(query);
        foreach (Asset attachment in queryResult.Assets)
        {
            VersionOne.SDK.apiclient.Attribute attribute = attachment.GetAttribute(contentTypeAttribute);
            string mimeType = "image/png";
            if (attribute != null)
            {
                mimeType = attribute.Value.ToString();
            }
            string extension = MimeTypestringToExtensionForImages(mimeType);
            string fileName = (countStored + 1) + "_" + extension;
            string attachmentID = attachment.Oid.Key.ToString();
            string content = attachment.GetAttribute(contentAttribute).Value.ToString();
            using (var fileStream = File.Create(filePath + "v1_img_" + fileName))
            {
                using (Stream blob = attachments.GetReadStream(content))
                {
                    blob.copyTo(fileStream);
                }

                countStored++;
            }
        }

        return result;
    }

在这一行遇到问题

using (Stream blob = attachments.GetReadStream(content))

服务器以这样的 404 响应: “远程服务器返回错误:(404) 未找到。'”

下面可以看到调试器中的值:

Debugged values

我已经对内容 (/VersionOne/embedded.img/2041732) 和附件 ID (2041732) 进行了尝试,但都导致了相同的错误

我应该使用什么来查找数据,或者我是否理解这个更严重错误并需要采用不同的方法

任何帮助将不胜感激!

解决方法

我想我找到了答案。不确定这是否是最好的答案,甚至是好的答案,但至少目前看来对我来说已经足够了。

“内容”是可以附加到 VersionOne 基本 URL 的路径,它们一起指向可以下载嵌入图像数据的位置。

所以我修改后的代码现在看起来像这样:

        public string StoreActiveV1ItemEmbeddedImages(PrimaryWorkitem v1Item,string targetPath,out int countStored)
    {
        string result = string.Empty;
        countStored = 0;
        if (v1Item == null) return "Error: No V1 item given to StoreActiveV1ItemEmbeddedImages!";
        string filePath = targetPath;
        if (!filePath.EndsWith("\\")) filePath += "\\";
        if (!Directory.Exists(filePath)) return "Error: Given path '" + filePath + "' does not exist!";
        IServices services = v1Instance.ApiClient.Services;
        IMetaModel metaModel = v1Instance.ApiClient.MetaModel;
        //IAttachments attachments = v1Instance.ApiClient.Attachments;
        Oid itemOid = services.GetOid(v1Item.ID.Token); 
        IAssetType assetType = metaModel.GetAssetType("EmbeddedImage");
        var query = new Query(assetType);
        IAttributeDefinition contentAttribute = assetType.GetAttributeDefinition("Content");
        IAttributeDefinition contentTypeAttribute = assetType.GetAttributeDefinition("ContentType");
        IAttributeDefinition assetAttribute = assetType.GetAttributeDefinition("Asset");
        query.Selection.Add(contentAttribute);
        query.Selection.Add(contentTypeAttribute);
        query.Selection.Add(assetAttribute);
        FilterTerm term = new FilterTerm(assetAttribute);
        term.Equal(itemOid.Momentless);
        query.Filter = term;
        QueryResult queryResult = services.Retrieve(query);
        foreach (Asset attachment in queryResult.Assets)
        {
            VersionOne.SDK.APIClient.Attribute attribute = attachment.GetAttribute(contentTypeAttribute);
            string mimeType = "image/png";
            if (attribute != null)
            {
                mimeType = attribute.Value.ToString();
            }
            string extension = MimeTypeStringToExtensionForImages(mimeType);
            string attachmentID = attachment.Oid.Key.ToString();
            string fileName = attachmentID + "_" + extension;
            string content = attachment.GetAttribute(contentAttribute).Value.ToString();
            string urlPath = Config.url;
            const string commonBit = "/VersionOne";
            if (urlPath.EndsWith(commonBit) && content.StartsWith(commonBit))
            {
                content = content.Replace(commonBit,string.Empty);
            }
            content = urlPath + content;
            string finalFileName = filePath + "v1_img_" + fileName;
            using (var client = new System.Net.WebClient())
            {
                client.Credentials = new System.Net.NetworkCredential(config.login,config.password);
                client.DownloadFile(content,finalFileName);
                countStored++;
            }
        }

        return result;
    }

因此 URL 是由配置数据和内容字符串构成的(只需进行一些处理以确保“VersionOne”在最终字符串中只出现一次),然后使用 WebClient 而不是 VersionOne API 从那里下载。