You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中能否调用Vuforia Web Service?求可用新增目标C#脚本

Vuforia云数据库添加目标时HTTP 400错误的解决及可用C#脚本

我已经花了一周时间编写脚本向Vuforia云数据库添加新目标,但一直收到HTTP 400错误请求。试过多种调整仍无效,求可用的C#脚本。

原问题代码

byte[] image = QRTexture.EncodeToPNG();
string base64 = Convert.ToBase64String(image); 
string jsonPayload = "{\"name\":\"" + firebaseID + "\"}, \"width\":32.0, \"image\":\"" + base64 + "\"}";
string requestPath = "/targets";
string serviceURI = url + requestPath;
string httpAction = "POST";
string contentType = "application/json";
string date = DateTime.Now.ToUniversalTime().ToString();
Debug.Log(date);

PostNewTrackableRequest model = new PostNewTrackableRequest
{
    name = firebaseID,
    width = 64.0,
    image = Convert.ToBase64String(image),
};
string requestBody = JsonConvert.SerializeObject(model);

WWWForm form = new WWWForm();

var headers = form.headers;
headers["host"] = url;
headers["date"] = date;
headers["Content-Type"] = contentType;

MD5 md5 = MD5.Create();
var contentMD5bytes = md5.ComputeHash(Encoding.ASCII.GetBytes(requestBody));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < contentMD5bytes.Length; i++)
{
    sb.Append(contentMD5bytes[i].ToString("x2"));
}

string contentMD5 = sb.ToString();

string stringToSign = string.Format("{0}\n{1}\n{2}\n{3}\n{4}", httpAction, contentMD5, contentType, date, requestPath);

HMACSHA1 sha1 = new HMACSHA1(Encoding.ASCII.GetBytes(secret_key));
byte[] sha1Bytes = Encoding.ASCII.GetBytes(stringToSign);
MemoryStream stream = new MemoryStream(sha1Bytes);
byte[] sha1Hash = sha1.ComputeHash(stream);
string signature = Convert.ToBase64String(sha1Hash);

headers["Authorization"] = string.Format("VWS {0}:{1}", access_key, signature);

Debug.Log("<color=green>Signature: " + signature + "</color>");
UnityWebRequest request = new UnityWebRequest(serviceURI, "POST");
request.SetRequestHeader("Content-Type", contentType);
request.SetRequestHeader("Authorization", "VWS "+access_key+":"+secret_key);
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(requestBody));
yield return request.SendWebRequest();

if (request.result == UnityWebRequest.Result.Success)
{
    Debug.Log("QR code uploaded successfully!");
}
else
{
    Debug.LogError("QR code upload failed!");
}

问题分析及修正点

  • Authorization头错误:原代码直接把secret_key放到Authorization头里,正确应该用计算出的signature
  • Date格式不符:Vuforia要求Date头必须是RFC1123标准格式(如"ddd, dd MMM yyyy HH:mm:ss GMT"),而非默认ToString格式
  • Host头设置错误:Host应该是Vuforia云服务的主机地址(如vws.vuforia.com),不是完整的serviceURI
  • 编码不一致:计算Content-MD5时用了ASCII编码,但requestBody是UTF8序列化的,需统一用UTF8
  • 缺少DownloadHandler:UnityWebRequest需要设置DownloadHandler才能读取错误响应内容,方便排查问题
  • 冗余代码:WWWForm的headers构建后未被使用,直接操作UnityWebRequest的头更简洁

修正后的可用脚本

using UnityEngine;
using UnityEngine.Networking;
using System;
using System.Text;
using System.Security.Cryptography;
using Newtonsoft.Json;

public class VuforiaCloudUploader : MonoBehaviour
{
    // 替换为你的Vuforia Access Key
    private string access_key = "YOUR_VUFORIA_ACCESS_KEY";
    // 替换为你的Vuforia Secret Key
    private string secret_key = "YOUR_VUFORIA_SECRET_KEY";
    // Vuforia云服务基础地址
    private string vuforiaBaseUrl = "https://vws.vuforia.com";

    [SerializeField] private Texture2D QRTexture;
    [SerializeField] private string firebaseID;

    public void UploadTrackable()
    {
        StartCoroutine(UploadNewTargetCoroutine());
    }

    private IEnumerator UploadNewTargetCoroutine()
    {
        if (QRTexture == null || string.IsNullOrEmpty(firebaseID))
        {
            Debug.LogError("QRTexture或firebaseID未设置");
            yield break;
        }

        byte[] imageBytes = QRTexture.EncodeToPNG();
        string base64Image = Convert.ToBase64String(imageBytes);

        // 构建请求模型
        var trackableModel = new PostNewTrackableRequest
        {
            name = firebaseID,
            width = 64.0f, // 根据实际目标宽度调整
            image = base64Image
        };
        string requestBody = JsonConvert.SerializeObject(trackableModel);
        byte[] requestBodyBytes = Encoding.UTF8.GetBytes(requestBody);

        string requestPath = "/targets";
        string serviceURI = vuforiaBaseUrl + requestPath;
        string httpAction = "POST";
        string contentType = "application/json";

        // 生成符合RFC1123标准的UTC时间
        string date = DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH:mm:ss GMT", System.Globalization.CultureInfo.InvariantCulture);
        Debug.Log("Request Date: " + date);

        // 计算Content-MD5
        string contentMD5;
        using (MD5 md5 = MD5.Create())
        {
            byte[] md5Bytes = md5.ComputeHash(requestBodyBytes);
            StringBuilder sb = new StringBuilder();
            foreach (byte b in md5Bytes)
            {
                sb.Append(b.ToString("x2"));
            }
            contentMD5 = sb.ToString();
        }

        // 构建待签名字符串
        string stringToSign = $"{httpAction}\n{contentMD5}\n{contentType}\n{date}\n{requestPath}";

        // 计算HMAC-SHA1签名
        string signature;
        using (HMACSHA1 sha1 = new HMACSHA1(Encoding.ASCII.GetBytes(secret_key)))
        {
            byte[] signatureBytes = sha1.ComputeHash(Encoding.ASCII.GetBytes(stringToSign));
            signature = Convert.ToBase64String(signatureBytes);
        }
        Debug.Log("<color=green>Generated Signature: " + signature + "</color>");

        // 创建UnityWebRequest
        using (UnityWebRequest request = new UnityWebRequest(serviceURI, httpAction))
        {
            request.uploadHandler = new UploadHandlerRaw(requestBodyBytes);
            request.downloadHandler = new DownloadHandlerBuffer();
            request.SetRequestHeader("Content-Type", contentType);
            request.SetRequestHeader("Date", date);
            request.SetRequestHeader("Host", "vws.vuforia.com");
            request.SetRequestHeader("Authorization", $"VWS {access_key}:{signature}");

            // 发送请求
            yield return request.SendWebRequest();

            // 处理响应
            if (request.result == UnityWebRequest.Result.Success)
            {
                Debug.Log("QR码上传成功!响应内容: " + request.downloadHandler.text);
            }
            else
            {
                Debug.LogError($"上传失败!错误码: {request.responseCode},错误信息: {request.downloadHandler.text}");
            }
        }
    }

    // 匹配Vuforia API的请求模型
    private class PostNewTrackableRequest
    {
        public string name { get; set; }
        public float width { get; set; }
        public string image { get; set; }
    }
}

使用说明

  1. 替换脚本中的access_key和secret_key为你的Vuforia开发者凭证
  2. 给QRTexture赋值要上传的目标图片,firebaseID设置目标名称
  3. 调用UploadTrackable()方法触发上传流程

内容的提问来源于stack exchange,提问作者dana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:53:21