-1

私はブラウザから直接ファイルをアップロードしようとしているopenstackオブジェクトストレージコンテナを持っています。JavaScriptからopenstackオブジェクトストレージにファイルをアップロードする

は、ドキュメントhereごととして、私はPUT要求を使用してファイルをアップロードすることができますし、私は以下に示すように、この使用Angularjsが$http.put方法を提供やっています。

$http.put(temporaryUploadUrl, 
    formData, 
    { 
     headers: { 
      'Content-Type': undefined 
     } 
    } 
).then(function (res) { 
    console.log("Success"); 
}); 

ファイルが正常にアップロードし、それが認証で問題がないと私に201 Created応答を与えます。しかし、ファイルには、マルチパート要求がFormData()を使用して送信されたため、上端と下端に迷惑線が含まれています。アップロードする前に

サンプルファイルの内容:

Some sample text 
here is more text 
here is some other text 

ファイル内容バックOpenStackのコンテナからdownloadiong後:

------WebKitFormBoundaryTEeQZVW5hNSWtIqS 
Content-Disposition: form-data; name="file"; filename="c.txt" 
Content-Type: text/plain 
Some sample text 
here is more text 
here is some other text 
------WebKitFormBoundaryTEeQZVW5hNSWtIqS-- 

私はバイナリ文字列として選択されたファイルを読むためにFileReaderを試してみましたFormDataの代わりにリクエスト本体に内容を書き込んだので、テキストファイルは正常に動作しますが、バイナリは正常に動作しませんyファイルXLSXまたはPDFのようなデータは完全にこの方法で破損しています。

+0

@georgeawgもう一度質問を再入力してください。私は間違いを編集しました –

+0

なぜこれらのすべてのdownvotesがなぜ私に言っているコメントがあった...:| –

+0

「迷惑行」は、Content-Type:multipart/formを送信する際の[境界](https://stackoverflow.com/questions/3508338/what-is-the-boundary-in-multipart-form-data)です。 - データ。 [ファイル](https://developer.mozilla.org/en-US/docs/Web/API/FileList)オブジェクトを直接送信する以外はすべて**試しました。 – georgeawg

答えて

1

私はバイナリ文字列として選択されたファイルを読むためにFileReaderを試してみましたが、代わりにFormDataのリクエストボディにコンテンツやテキストファイルの正常に動作要求ではなく、XLSXやPDFなどのバイナリファイルを書きましたデータはこのように完全に破損しています。

$http serviceのデフォルトの動作は、Content-Type: application/jsonを使用し、JSON stringsにオブジェクトを変換することです。

var config = { headers: {'Content-Type': undefined} }; 

$http.put(url, fileList[0], config) 
    .then(function(response) { 
    console.log("Success"); 
}).catch(function(response) { 
    console.log("Error: ", response.status); 
    throw response; 
}); 

Content-Type: undefinedを設定することにより、XHR send methodが自動的に適切にコンテンツタイプヘッダを設定します:FileListからファイルのために、デフォルト値をオーバーライドする必要があります。

base64 encoding'Content-Type': multipart/form-dataの場合、33%のオーバーヘッドが発生することに注意してください。 BlobsFileオブジェクトを直接送信する方が効率的です。

バイナリ文字列としてバイナリデータを送信すると、XHR APIDOMSTRING (UTF-16)からUTF-8に文字列を変換するため、データが破損します。 binary stringsは標準ではなく、時代遅れですので避けてください。

+0

私はこれを試します... –

+0

これは、私がOpenstackのtemp URLにアップロードしようとしたときに動作しませんでした。ファイルエントリは作成されますが、ファイルは0バイトとしてダウンロードされます(空のファイル) –

+0

あなたのコードで 'transformRequest:angular.identity'を削除することで修正しました。私はそれを受け入れるためにあなたの答えを更新してください。 –

2

EDIT:

次の答えは、今ではマルチパートフォームデータをbase64でファイル全体をエンコードします としてはあまりパフォーマンスの回避策を検討しています。あなたは formData + POSTソリューションをお探しされていない場合、私は は@ georgeawgの回答を進めることをお勧め

OpenStackのも、この中で述べたように、単一の回で、1つまたは複数のファイルをアップロードするためのいるFormDataを使用して、異なるアプローチを提供documentation。面白いこれはGoogle検索では決して見えませんでした。

ここにその概要を示します。

まず、次のpythonプロシージャを使用して、tempUrlシグネチャに似たシグネチャを生成する必要があります。

import hmac 
from hashlib import sha1 
from time import time 
path = '/v1/my_account/container/object_prefix' 
redirect = 'https://myserver.com/some-page' 
max_file_size = 104857600 
max_file_count = 1 
expires = 1503124957 
key = 'mySecretKey' 
hmac_body = '%s\n%s\n%s\n%s\n%s' % (path, redirect, 
max_file_size, max_file_count, expires) 
signature = hmac.new(key, hmac_body, sha1).hexdigest() 

次に、このようなコンテナへのjavascriptコールポストで。

var formData = new FormData(); 
formData.append("max_file_size", '104857600'); 
formData.append("max_file_count", '1'); 
formData.append("expires", '1503124957'); 
formData.append("signature", signature); 
formData.append("redirect", redirect); 
formData.append("file",fileObject); 
$http.post(
    "https://www.example.com/v1/my_account/container/object_prefix", 
    formData, 
    { 
     headers: {'Content-Type': undefined}, 
     transformRequest: angular.identity 
    } 
).then(function (res) { 
    console.log(response); 
}); 

点は注意します。

  • formDataPOSTでの要求は、これらの のパラメータを含める必要があります。
  • formDataのファイルエントリが最後のものである必要があります(なぜ が別の方法で動作しないのか分かりません)。
  • 接頭辞、エポックタイム、最大ファイル サイズ、最大ファイル数、およびリダイレクトURLを持つパスのようなformDataコンテンツは、署名の生成に使用された と同じである必要があります。そうしないと、 は401 Unauthorizedになります。
関連する問題