2

htmlフォームを歌わずにajax経由でファイルをアップロードする際に問題が発生しています。私の場合は次のようになります。

  1. テキストエリアがあります
  2. そのテキストエリアのコンテンツをzipして、AJAX経由でサーバーにアップロードしたいと思います(現在、JSZipを使用しています) 。
  3. テストの目的で、次のように送信するダミーのzipファイルを作成しようとします(textareaコンテンツを取得しません)。

    var zip = new JSZip();
    zip.file("hello1.txt", "Hello First World\n");<br/>
    zip.file("hello2.txt", "Hello Second World\n");<br/>
    var content = zip.generate();
    
  4. 次に、Jqueryajaxメソッドを使用して次のように送信します。

    $.post("the_url",
        {
            GradeRequest : {
                submitter_id : "foobar",
                evaluationset_id : 9,
                mode : 1,
                source_file : "a.cpp",
                file: content
            }
        }
    );
    

ただし、ファイルはサーバーで受信されません。非同期でファイルをアップロードするにはどうすればよいですか?の質問を読みました。、ただし、すべてのソリューションはhtmlフォームを使用しています。htmlフォームを含まないソリューションはありますか?

前もって感謝します。

サーバー側では、YiiPHPFrameworkを使用しています。

$model = $this->model;
    if ($model !== null && isset($_POST['GradeRequest'])) {
        $model->setAttributes($_POST['GradeRequest']);

        if ($model->validate()) {
            if (isset($_FILES['GradeRequest']['tmp_name']['file']) && $_FILES['GradeRequest']['tmp_name']['file'] !== "") {
                $model->file = file_get_contents($_FILES['GradeRequest']['tmp_name']['file']);
                $model->source_file = $_FILES['GradeRequest']['name']['file'];
            }

            $this->setReply(true, "Ok");
            $model->client_id = $this->clientId;
            $model->request_id = $this->requestRecord->id;
            $model->save();
        } else {
            $this->setReply(false, $model->getErrors());
        }
    }

概念実証として、私はこのようなフォームバージョンを作成し、それが機能します(ファイルがサーバーにアップロードされました)。

<form enctype="multipart/form-data" method="post" action="[the_url]>
EvaluationSet id: <input type="text" name="GradeRequest[evaluationset_id]" /><br />
<input type="hidden" name="GradeRequest[mode]" value="0" />
<input type="hidden" name="GradeRequest[submitter_id]" value="Someone" />

Source file : <input type="text" name="GradeRequest[source_file]" /><br />
File : <input type="file" name="GradeRequest[file]" /><br />

<input type="submit" />

4

2 に答える 2

3

あなたを助けることができるオブジェクトがありFormDataます(いわゆるxmlHttpRequestバージョン2の一部です):これは、いくつかのリンクされた参照と例を含む互換性チャートです。

これにより、オブジェクトを含むキーと値のペアを POST フォームに追加Fileし、 の共通sendメソッドを介してすべてを送信できますxmlHttpRequest

File<input type="file">オブジェクトは、要素を使用して、またはデスクトップからドラッグ & ドロップを使用して簡単に取得できます。

一部のファイルコンテンツをファイルとしてアップロードする場合は、Blob. この機能はまだ実験段階ですが、Chrome と Firefox でサポートされています (少なくとも...そして Safari でしょうか?):

var builder = new BlobBuilder();
builder.append(content);
var blob = builder.getBlob("application/zip");

現時点では、代わりMozBlobBuilderに Firefox とWebKitBlobBuilderChrome で使用する必要があることに注意してください。

いくつかのチュートリアルで、文字列が実際に最初に変換されることを見てきましたUint8ArrayappendのメソッドはBlobBuilderプレーン文字列も受け入れる必要があるため、古いリファレンスに基づいている可能性があります。しかし、それを試したことはありません。

コンテンツが Base64 でエンコードされた文字列の場合は、 を使用して変換する必要があります (およびatobもサポートするすべてのブラウザーでサポートされている必要があります)。BlobFormData

Edit : BlobBuilderBlob コンストラクターの新しいドラフトにより、現在は非推奨です。したがって、取得するために必要なことBlobは次のとおりです。

var blob = new Blob([content], "application/zip");

残りは非常に簡単です。

var form = new FormData();
form.append("file", blob);

ここでの問題は、サーバー側のファイル名が予測不能であり、ユーザー エージェントに依存することです。ファイル名を指定する 3 番目のパラメーターを使用したの使用を見てきましappendたが、実際のファイル名をFormDataオブジェクト内の別のキーと値のペアに送信することをお勧めします。

于 2012-06-17T09:42:57.673 に答える
1

やっと通じます!!MaxArtに感謝します。

基本的には、Uint8Array 変換でMaxArtが言っていることです。ここで Eric Bidelman から変換リファレンスを入手しました。

これが私がやった方法です:

var zip = new JSZip();
zip.file("hello1.txt", "Hello First World\n");
zip.file("hello2.txt", "Hello Second World\n");
var content = zip.generate(); //Generate dummy zip file (adjust to your need)

var oBlob = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder)(); //Instantiate blob builder

var raw = atob(content);    //decode the base64 string
var rawLength = raw.length;
var uInt8Array = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; ++i) { //convert to uInt8Array
    uInt8Array[i] = raw.charCodeAt(i);
}

oBlob.append(uInt8Array.buffer); //append it to blobbuilder
oMyForm.append("GradeRequest[file]", oBlob.getBlob("application/zip")); //because you create a zip file, so get the zip type

//send it
var oReq = new XMLHttpRequest();
oReq.open("POST", "{{the_url}}");
oReq.send(oMyForm);
于 2012-06-17T17:59:30.140 に答える