2017-09-25 40 views
3

私はのHttpRequest経由hololensメガネと通信するデスクトップ・アプリケーションで作業(hololensは、USBを介して接続されている)、特に、私は、ファイルを読み書きしたいです。これを行うには、私は次のコードを使用し、それを実行するには転送ファイル(エラー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; 
    } 
} 

を私はGETFILEメソッドが正常に動作し、私がしたいファイルを与えるが、UploadFileメソッドは私に次のような応答を与え

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"); 
を呼び出します:StatusCode:429、ReasonPhrase: 'Too Many Requests'。実行中にそのうちの1つだけを実行すると同じ結果になります。

なぜ私はこのエラーがあるのか​​分かりません。私はちょうど1つのリクエストを送信します(または何か不足しています)。

詳細については、REST APIの定義はthereです。 (このエラー429が表示される理由)

おかげ

+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

問題に

のデバッグ問題がクローム61 multipart/form-dataとして正しくcontent-typeヘッダを送信しなかった一方、クロム62は、空のcontent-typeヘッダを送信していることです。

原因はFileExplorer.jsのためのMicrosoftの独自のコードがcontentType: ""jQuery.ajax(...)を呼び出し、そのブラウザが空の文字列を解釈するために残っていたということです。

$.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 FileExplorer.jsから

抜粋は、リクエストヘッダのいずれかを指定することができない、リクエストボディを指定することができないので、正しいセットを決定するに対する何らの仕様は存在しませんヘッダーとボディ。

FWIW、Microsoft自身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

これは正しいです - これはDevice Portalのそれ以降のバージョンで修正されましたが、HoloLensはまだアップデートを行っていません。この問題を回避するには、更新されていないIEを使用して、「適切に」エンコードされたリクエストを送信します。 これを解決するドキュメントがある場合は、教えてください。私はMSDNでドキュメントを編集します。 –

+0

@HirschSinghal確認と内部情報をありがとう。 '/ api/filesystem/apps/file'の' POST'が 'multipart/form-data'の' ContentType'ヘッダを必要とし、ペイロードをそのように送ることを要求するREST APIドキュメント状態を持つことが理想的です。さらに、空の 'ContentType'ヘッダーに多すぎるリクエストを429で返すAPIは、400 Bad Requestや412 Precondition Failedなどのより適切なステータスコードに置き換えることができます。 – doublerebel

+0

@HirschSinghal残念ながら、EdgeはXHR呼び出しをChromeやFirefoxと同じように解釈し、コンテンツタイプを空の文字列から訂正しません。私は、Chrome上で動作するブックマークレットを私のソリューションに追加し、クロスブラウザで動作するはずです。編集:デバイスポータルでJSONPがサポートされていれば、他の回避策を使用できる可能性があります。 FileExplorer.jsのオブジェクトインスタンスとメソッドはすべてクロージャで作成されるので、私はそれをモンキーパッチすることはできません。また、CSRFトークンがCookie /ヘッダーにあり、Device Portal REST APIからのCORSサポートが不足しているため、CORSも例外ではありません。 – doublerebel

0

は、私は本当に私の質問に答えていませんが、私はファイルをアップロードするための代替ソリューションを提供します。

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");