我尝试了很多变化 - 我在下面发布的是一个清理版本,我最初开始使用的版本。这是一个帮助实用程序我正在为基于Unity的应用程序编写。它不是游戏,只是一个2D应用程序。
我试图复制这个:
curl -f -s -S --user $(ROKU_DEV_CREDENTIALS) --anyauth -F "mysubmit=Install" -F "archive=@out/Archive.zip" http://$(ROKUIP)/plugin_install > /dev/null
这是我到目前为止(见下面的代码) - 似乎是"有点"工作,但允许auth通过,大约108 KB的数据(wireshark说,整个ZIP,大约2.8 MB,正在发送,但服务器说只收到大约108 KB);我想也许这可能是一个编码问题(应用程序在Windows 10上,而Server是嵌入式Linux服务器[Roku Player])。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
public class PushBuild : MonoBehaviour {
public RokuDevice SingleDevice;
public Dictionary<string, RokuDevice> ManyDevice;
public bool startUpload;
// Use this for initialization
void Start() {
}
// Update is called once per frame
void Update() {
if (startUpload)
{
StartCoroutine(Upload());
startUpload = false;
}
}
public void QueueUpPush()
{
startUpload = true;
}
IEnumerator Upload()
{
string[] substr = null;
UnityWebRequest www1 = UnityWebRequest.Head("http://10.0.0.232/plugin_install");
yield return www1.Send();
if (www1.isError)
{
Debug.Log(www1.error);
}
else
{
Dictionary<string, string> responseHeaders = www1.GetResponseHeaders();
string nonce;
string[] split = { "=", "\"" };
bool _null = responseHeaders.TryGetValue("WWW-Authenticate", out nonce);
if (nonce != null)
{
substr = nonce.Split(split, StringSplitOptions.RemoveEmptyEntries);
}
}
WWW _file = new WWW("file:///" + "D:\\Workspace\\Roku\\Tempest\\src\\Archive.zip");
yield return _file;
WWWForm form = new WWWForm();
form.AddBinaryData("archive", _file.bytes, "Archive.zip", "application/x-zip-compressed");
form.AddField("mysubmit", "install");
using (UnityWebRequest www = UnityWebRequest.Post("http://10.0.0.232/plugin_install", form))
{
string ha1 = "rokudev:rokudev:0000";
string ha2 = "POST:/plugin_install";
string responseDigest = CalculateResponseDigest(ha1, ha2, substr[5], "00000000", "aef3fafadfaedfadf", "auth");
string authHeaderVal = string.Format("Digest username=\"rokudev\", realm=\"rokudev\", nonce=\"{0}\", uri=\"/plugin_install\", response=\"{1}\", qop=auth, nc=00000000, cnonce=\"aef3fafadfaedfadf\"", substr[5], responseDigest);
www.SetRequestHeader("Authorization", authHeaderVal);
www.Send();
while (www.uploadProgress < 1.0)
{
Debug.Log("still uploading..." + www.uploadProgress);
yield return null;
}
Debug.Log(www.uploadedBytes);
if (www.isError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
Debug.Log(www.downloadHandler.data);
}
}
}
string CalculateResponseDigest(string ha1, string ha2, string serverNonce, string requestCnt, string clientNonce, string qop)
{
byte[] inputBytesHA1 = Encoding.ASCII.GetBytes(ha1);
byte[] HA1 = MD5.Create().ComputeHash(inputBytesHA1);
StringBuilder _returnValHA1 = new StringBuilder(HA1.Length * 2);
foreach (byte b in HA1)
{
_returnValHA1.AppendFormat("{0:x2}", b);
}
byte[] inputBytesHA2 = Encoding.ASCII.GetBytes(ha2);
byte[] HA2 = MD5.Create().ComputeHash(inputBytesHA2);
StringBuilder _returnValHA2 = new StringBuilder(HA2.Length * 2);
foreach (byte b in HA2)
{
_returnValHA2.AppendFormat("{0:x2}", b);
}
byte[] inputBytesHA3 = Encoding.ASCII.GetBytes(string.Format("{0}:{1}:{2}:{3}:{4}:{5}", _returnValHA1, serverNonce, requestCnt, clientNonce, qop, _returnValHA2));
byte[] HA3 = MD5.Create().ComputeHash(inputBytesHA3);
StringBuilder _returnVal = new StringBuilder(HA3.Length * 2);
foreach (byte b in HA3)
{
_returnVal.AppendFormat("{0:x2}", b);
}
return _returnVal.ToString();
}
}
重要提示:
FileStream
。我试过建一个
原始C#HttpWebRequest
。我尝试过匹配Roku的标头
的准确即可。 我有wirehark数据,fiddler数据,以及我可以分享的5种不同的实现(与上面的例子不同)。我甚至可以分享Roku的嵌入式WebApplication所使用的JavaScript,以显示它正在做什么(它是使用digest auth进行的POST - 有点直接)。告诉我你错过了什么 - 我现在已经打了2个星期了,最后还是去寻求帮助!
有什么想法吗?
答案 0 :(得分:0)
这个问题归结为“我如何从c#进行http POST”和“我如何从c#进行摘要身份验证” - 如果你谷歌这个,一些S.O.答案很流行,请遵循这些。
编码与它无关,ZIP以原始八位字节的形式提交。
这是故障排除(分而治之)的想法 - 首先教你的应用程序上传小型ZIP,<100k。编写一个简单的BrightScript应用程序(Hello World),看看你的代码可以成功上传。然后专注于更大的尺寸 - 例如,您的客户端可能尝试使用chunked-encodding,而服务器不支持它。我的观点是 - 从简单开始,走向完整的案例