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; } } }
使用说明
- 替换脚本中的
access_key和secret_key为你的Vuforia开发者凭证 - 给
QRTexture赋值要上传的目标图片,firebaseID设置目标名称 - 调用
UploadTrackable()方法触发上传流程
内容的提问来源于stack exchange,提问作者dana
相关产品推荐
相关产品推荐

