2017-09-25 94 views
3

我通過的HttpRequest上的桌面應用程序與hololens眼鏡溝通工作(hololens通過USB連接),特別是,我想讀寫文件。要做到這一點,我使用下面的代碼:文件傳送到hololens(錯誤429)

class BuildDeployPortal 
{ 
    // Consts 
    public static readonly string API_FileQuery = @"http://{0}/api/filesystem/apps/file"; 

    // Classes & Structs 
    public struct ConnectInfo 
    { 
     public ConnectInfo(string ip, string user, string password) 
     { 
      IP = ip; 
      User = user; 
      Password = password; 
     } 

     public string IP; 
     public string User; 
     public string Password; 
    } 

    public async static void GetFile(ConnectInfo connectInfo, string knownfolderid, string filename, string packagefullname, string path) 
    { 
     try 
     { 
      // Query 
      string query = string.Format(API_FileQuery, connectInfo.IP); 
      query += "?knownfolderid=" + Uri.EscapeUriString(knownfolderid); 
      query += "&filename=" + Uri.EscapeUriString(filename); 
      query += "&packagefullname=" + Uri.EscapeUriString(packagefullname); 
      query += "&path=" + Uri.EscapeUriString(path); 

      // Create http request 
      var httpRequest = new HttpClient(); 

      httpRequest.DefaultRequestHeaders.Clear(); 
      httpRequest.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", 
                         EncodeTo64(connectInfo.User + ":" + connectInfo.Password)); 

      HttpResponseMessage resp = await httpRequest.GetAsync(query); 

      byte[] responseMessage = await resp.Content.ReadAsByteArrayAsync(); 

     } 
     catch (Exception ex) 
     { 
      //log some problems 
     } 

    } 



    public async static void UploadFile(ConnectInfo connectInfo, string knownfolderid, string packagefullname, string path, string filePath) 
    { 
     try 
     { 
      // Query 
      string query = string.Format(API_FileQuery, connectInfo.IP); 
      query += "?knownfolderid=" + Uri.EscapeUriString(knownfolderid); 
      query += "&packagefullname=" + Uri.EscapeUriString(packagefullname); 
      query += "&path=" + Uri.EscapeUriString(path); 

      // Create http request 
      var httpRequest = new HttpClient(); 

      httpRequest.DefaultRequestHeaders.Clear(); 
      httpRequest.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", 
                         EncodeTo64(connectInfo.User + ":" + connectInfo.Password)); 
      byte[] data = File.ReadAllBytes(filePath); 
      ByteArrayContent byteContent = new ByteArrayContent(data); 

      HttpResponseMessage resp = await httpRequest.PostAsync(query, byteContent); 

      var responseMessage = await resp.Content.ReadAsStringAsync(); 

     } 
     catch (Exception ex) 
     { 
      //log some problems 
     } 

    } 


    // Helpers 
    private static string EncodeTo64(string toEncode) 
    { 
     byte[] toEncodeAsBytes = Encoding.ASCII.GetBytes(toEncode); 
     string returnValue = Convert.ToBase64String(toEncodeAsBytes); 
     return returnValue; 
    } 
} 

要運行它,我打電話

BuildDeployPortal.ConnectInfo co = new BuildDeployPortal.ConnectInfo("127.0.0.1:10080", "user", "pass"); 

//get file 
BuildDeployPortal.GetFile(co, "LocalAppData", "2017-01-25-09-04-21_TestFile.csv", "app_full_package_name", "\\LocalState"); 

//upload file 
BuildDeployPortal.UploadFile(co, "LocalAppData", "app_full_package_name", "\\LocalState", 
      "C:\\Users\\myuser\\Desktop\\info.json"); 

GetFile方法工作得很好,給我我想要的文件,但UploadFile方法給了我以下響應:狀態碼:429,ReasonPhrase:'太多請求'。如果我在執行期間只運行其中一個,結果也是一樣。

我真的不明白爲什麼我有這個錯誤,我只發送1個請求(或者我錯過了一些東西)。

有關信息,可以找到REST API的定義there

感謝

+0

我收到了同樣的結果。我已將此代碼/問題複製到HoloLens論壇:https://forums.hololens.com/discussion/8749/transfer-file-to-hololens-via-post-httprequest-error-429 - 但還沒有看到迴應那裏。我真的跳了這個解決。 –

+0

opps,我發現這也是你的帖子。我有一個比這更早一點,https://forums.hololens.com/discussion/8736/trying-to-upload-1-files-returns-429-too-many-requests沒有迴應。如果您得到答案,請在此處張貼。 - 謝謝。 –

+0

對不起,丹,我沒有答案,只是一個替代... –

回答

1

調試問題

的問題是,Chrome瀏覽器62將空content-type頭,而Chrome的61 正確發送content-type頭爲multipart/form-data

原因是微軟自己的FileExplorer.js代碼調用jQuery.ajax(...)contentType: "",所以瀏覽器被留下來解釋一個空字符串。從FileExplorer.js

摘錄

$.ajax({url:"/api/filesystem/apps/file?"+$.param(r),cache:!1,contentType:"",processData:!1,data:n,type:"post"}).done(...) 

REST API definition you linked from Microsoft沒有指定任何請求頭,並沒有指定請求主體,所以針對其確定正確的一組無規範頭和身體。

FWIW,微軟自己C# Device Portal REST API wrapper總是發送Content-Type頭:

string contentType = string.Format("multipart/form-data; boundary={0}", boundaryString); 

解決方案

我創建了一個書籤,將正確的時候上傳的文件在設備門戶FileExplorer頁面上。

擴大版

(function(jQuery) { 
var pathLinkData = jQuery(".pathLink:last-child").data(), 
    path = pathLinkData.path, 
    packagename = pathLinkData.packagename, 
    knownfolderid = pathLinkData.knownfolderid, 
    url = '/api/filesystem/apps/file?knownfolderid=' + knownfolderid + '&packagefullname=' + packagename + '&path=%5C%5C' + path, 
    file_data = jQuery('#fileToUpload')[0].files[0], 
    form_data = new FormData(); 

    form_data.append('file', file_data, file_data.name); 

    jQuery.ajax({ 
    url: url, 
    dataType: 'text', 
    cache: false, 
    contentType: false, 
    processData: false, 
    data: form_data, 
    type: 'POST', 
    error: function(xhr, textStatus, error) { console.error(error) }, 
    success: function(res){ 
     alert('uploaded'); 
     console.log(res); 
    } 
    }); 
})(jQuery); 

緊湊型可複製書籤版本(也適用於檢查/調試器控制檯)

javascript:(function(jQuery){var pathLinkData=jQuery('.pathLink:last-child').data(),path=pathLinkData.path,packagename=pathLinkData.packagename,knownfolderid=pathLinkData.knownfolderid,url='/api/filesystem/apps/file?knownfolderid='+knownfolderid+'&packagefullname='+packagename+'&path=%5C%5C'+path,file_data=jQuery('#fileToUpload')[0].files[0],form_data=new FormData();form_data.append('file',file_data,file_data.name);jQuery.ajax({url:url,dataType:'text',cache:false,contentType:false,processData:false,data:form_data,type:'POST',error:function(xhr,textStatus,error){console.error(error)},success:function(res){alert("uploaded");console.log(res);}});})(jQuery); 

(我一直在Hololens開發了一年,發現這是每個我的電腦分別升級到Chrome 62.)

+0

這是正確的 - 這已被更高版本的設備門戶中修復,但HoloLens尚未採取更新。爲了解決這個問題,您可以使用尚未更新的IE,併發送一個「正確」編碼的請求。 如果有文檔可以幫助解決這個問題,請告訴我,我將在MSDN上編輯文檔。 –

+0

@HirschSinghal感謝您的確認和內部信息。如果REST API文檔聲明'POST'爲'/ api/filesystem/apps/file'需要'multipart/form-data'的'ContentType'頭文件並且需要這樣發送有效載荷,那將是理想的。 (也可能有一個查詢參數也需要嗎?)此外,API響應429太多的請求到一個空的「ContentType」頭可能會被一個更合適的狀態代碼,如400錯誤請求或412先決條件失敗。 – doublerebel

+0

@HirschSinghal不幸的是,Edge將XHR調用解釋爲與Chrome和Firefox相同,並且不會從空字符串中更正內容類型。我在我的解決方案中添加了一個可在Chrome上運行的小書籤,並且可以跨瀏覽器工作。編輯:這將是偉大的,如果設備門戶支持JSONP,那麼我可能已經能夠使用其他解決方法。 FileExplorer.js中的所有對象實例和方法都是在閉包中創建的,所以我不能對其進行修補。由於CSRF令牌位於cookie /頭中,加上缺少來自Device Portal REST API的CORS支持,因此CORS也不存在。 – doublerebel

0

我真的不回答我的問題(爲什麼這個錯誤出現429),但我得到的替代解決方案上傳文件。

我下載this solution得到WindowsDevicePortalWrapper庫。 後來我叫下面的代碼上傳文件:

IDevicePortalConnection connection = new DefaultDevicePortalConnection("http://127.0.0.1:10080", "user", "password"); 
DevicePortal dp = new DevicePortal(connection); 
//write file 
await dp.UploadFileAsync("LocalAppData", "C:\\Users\\ng1dd32\\Desktop\\info.json", "\\LocalState", "Lexington_1.0.0.0_x86__ph1m9x8skttmg");