2016-07-21 5 views
0

私たちが作業しているウェブサイトには、ダウンロードリンクがあります。このリンクはユーザーに提供する必要があります。ただし、URLを取得するときに、サーバーはJSONでエラーメッセージを表示するか(適切なヘッダーと適切なhttpステータスコードが設定されます)、またはファイルを提供することができます。大きなファイルをダウンロードするか、エラーを表示します

現在、私たちはこのファイルをダウンロードするためにiframeを使用していますが、これによりエラーメッセージは表示されません。これは原則的には可能ですが、クロスドメインではできませんし、ブラウザ間でエラーデータの読み方が異なるように見えます(ブラウザがjsonをHTMLと解釈し、HTMLタグとしてHTMLタグを作成するので)。

I xmlhttprequest2を使用してファイルをダウンロードしてユーザーに提供することを検討しましたが、ダウンロードされたファイルは大きくなる可能性があるため、ユーザーにストリーミングする必要があります。

したがって、私はファイルをダウンロードするか、httpステータスコードに応じてエラーメッセージを読む方法を探しています。私は私の希望にAPIを変更することができるよ

APIのセットアップ

は、しかし、APIは、公開APIになるように設計されており、RESTのAPIとして設計されています。これは、APIができるだけシンプルに保たれるべきであり、特定のクライアント側のコードを動作させるための回避策が、他のクライアント側のために(つまり、APIとクライアント側のコードが分離されていないように)

ダウンロードされているファイルは、サーバー上で暗号化されており、URLに記載された情報でのみ解読できます。したがって、チャンクを抽出すると、サーバーがファイル全体を復号化する必要があるため、チャンク転送は困難です。

+0

サーバーの応答を制御できますか?エラーコードとエラーメッセージ、または成功コードとファイルURLのいずれかに応答を変更できますか?もしそうなら、あなたはajax呼び出しを行い、成功すればurlにリダイレクトできます。これで問題が解決しない場合は、セットアップがどうしたらこの問題を回避できるか説明してください。 – TinMonkey

+0

'MIME'形式のファイルはどのようなものでしょうか? – guest271314

+0

@TinMonkeyはい、あります。しかし、一般的に、エラーは例外で、私はむしろ1つのリクエストをしたいと思っていますが、私はちょうど以下に説明するHEADアプローチを使って実装を始めました。それはREST APIにも関係しているので、そのようなリダイレクトは実際にはデザインには適合しませんが、もちろんHEADのアプローチは:)。 – user23127

答えて

3

適切なヘッダおよび適切なHTTPステータスコードは、その文が正しければ、あなたはクロスサイトリクエストに対するpreflighted requestsと同じ概念を使用することができ

に設定されます。プリフライトされたリクエストは、最初にOPTIONSメソッドでHTTPリクエストを他のドメインのリソースに送信し、実際のリクエストが安全かどうかを判断します。

お客様の場合、OPTIONSリクエストを自動的に送信する代わりに、HEADリクエストを手動で送信することができます。 HEADメソッドは、サーバがレスポンスでメッセージ本体を返さないことを除いて、GETと同じです。 HEAD要求に応答してHTTPヘッダーに含まれる情報は、GET要求に応答して送信される情報と同じである必要があります。あなたは本体だけでなくヘッダだけを取得しているので、大きなファイルやファイルでも問題はなく、ヘッダ以外のものはダウンロードされません。

これらのヘッダーまたは状態コードを読み取ることができます。この手動でプリフライトされたリクエストの結果に応じて、ファイルをユーザーにストリームするか、エラーメッセージが表示されるかどうかを決定します。エラー。ステータスコードを使用してプロジェクトの知識がなくて

基本的な実装には、次のようになります。

function canDownloadFile(url, callback) 
{ 
    var http = new XMLHttpRequest(); 
    http.open('HEAD', url); 
    http.onreadystatechange = function() { 
    if (http.readyState === XMLHttpRequest.DONE) { 
     callback(http.status); 
    } 
    }; 

    http.send(); 
} 

var canDownloadCallback = function (statusCode) { 
    if (statusCode === 200) { 
    // The HEAD request returned an OK status code, the GET will do the same, 
    // let's download the file... 
    } else { 
    // The HEAD request returned something else, something is wrong, 
    // let's fetch the error message and maybe display it... 
    } 
} 
+0

ねえ、これはまさに私が今実装しているものです!私は単一の要求の代替案があることを望んでいましたが、そうでなければ、あなたの答えを受け入れます。 – user23127

0

あなたは、単一の要求を使用Blobとして応答を返す。ここで、取得するためにFileReader.resultを利用するかを決定するためにBlob.typeをチェックできますJSONBlobからテキストと表示エラーメッセージ、またはURL.createObjectURL

var result = document.querySelector("div"); 

fetch("/path/to/resource") 
.then(response => response.blob()) 
.then(blob => { 
    if (blob.type === "application/json") { 
    var reader = new FileReader(); 
    reader.onload = (e) => { 
     result.innerHTML = JSON.parse(e.target.result).error 
    }; 
    reader.readAsText(blob); 
    } else { 
    var img = document.createElement("img"); 
    img.src = URL.createObjectURL(blob); 
    result.appendChild(img); 
    } 
}); 
を用い <img>要素の srcを設定します3210

plnkr http://plnkr.co/edit/wrzLNm1Sp4k1mfNrYOlQ?p=preview

+0

これは大きなファイルで機能しますか?これはファイル全体をメモリにロードするでしょうか? – user23127

+0

@ user23127 _ "これは大きなファイルでも機能しますか?" _試しましたか? – guest271314

+0

私はそれがないと確信しています。 – user23127

1

postrameを介して親ウィンドウにメッセージを送信するiframe JSコードに戻ることができます。この方法でホストウィンドウにエラーをキャプチャできます。クロスドメインには何の問題もなく、コンテンツは以前のようにブラウザに簡単にストリーミングされます。

+0

それは私がサーバーの応答を必ずしもブラウザではないクライアントの応答に合わせることを必要とするでしょう。 – user23127

関連する問題