Korzystanie z HTML5 przesyłanie plików z AJAX i jQuery

Wprawdzie podobne pytania leżą na Stack Overflow, ale wydaje się, że żadne nie spełnia moich wymagań.

Oto co chcę zrobić:

  • Prześlij całą formę danych, z których jedna część to pojedynczy plik
  • Praca z biblioteką przesyłania plików Codeigniter
Do tej pory wszystko jest w porządku. Dane trafiają do mojej bazy danych tak, jak tego potrzebuję. Ale chciałbym również przesłać mój formularz za pośrednictwem posta AJAX:
  • używanie natywnego HTML5 File API, Nie flash lub rozwiązanie iframe
  • najlepiej współpracować z metodą low-level .ajax() jQuery

Myślę, że mogę sobie wyobrazić, jak to zrobić przez automatyczne przesyłanie pliku, gdy wartość pola zmienia się za pomocą czystego javascript, ale wolałbym zrobić to wszystko za jednym zamachem na submit w jQuery. Myślę, że nie da się tego zrobić za pomocą łańcuchów zapytań, ponieważ muszę przekazać cały obiekt pliku, ale jestem trochę zagubiony w tym momencie.

Czy to może być / align = "left" /

Author: SiHa, 2010-10-24

2 answers

To nie jest zbyt trudne. Po pierwsze, spójrz na interfejs FileReader.

Tak więc, gdy formularz jest złożony, złapać proces składania i

var file = document.getElementById('fileBox').files[0]; //Files[0] = 1st file
var reader = new FileReader();
reader.readAsText(file, 'UTF-8');
reader.onload = shipOff;
//reader.onloadstart = ...
//reader.onprogress = ... <-- Allows you to update a progress bar.
//reader.onabort = ...
//reader.onerror = ...
//reader.onloadend = ...


function shipOff(event) {
    var result = event.target.result;
    var fileName = document.getElementById('fileBox').files[0].name; //Should be 'picture.jpg'
    $.post('/myscript.php', { data: result, name: fileName }, continueSubmission);
}

Następnie po stronie serwera (np. myscript.php):

$data = $_POST['data'];
$fileName = $_POST['name'];
$serverFile = time().$fileName;
$fp = fopen('/uploads/'.$serverFile,'w'); //Prepends timestamp to prevent overwriting
fwrite($fp, $data);
fclose($fp);
$returnData = array( "serverFile" => $serverFile );
echo json_encode($returnData);

Albo coś w tym stylu. Może się mylę (i jeśli tak, proszę mnie poprawić), ale to powinno zapisać plik jako coś w rodzaju 1287916771myPicture.jpg w /uploads/ na twoim serwerze i odpowiedzieć zmienną JSON (na funkcję continueSubmission()) zawierającą nazwę pliku na serwer.

Zobacz fwrite() oraz jQuery.post().

Na powyższej stronie szczegółowo opisano jak używać readAsBinaryString(), readAsDataUrl(), oraz readAsArrayBuffer() dla innych Twoich potrzeb(np. zdjęcia, filmy itp.).

 86
Author: clarkf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-30 21:34:15

Z jQuery (i bez FormData API) możesz użyć czegoś takiego:

function readFile(file){
   var loader = new FileReader();
   var def = $.Deferred(), promise = def.promise();

   //--- provide classic deferred interface
   loader.onload = function (e) { def.resolve(e.target.result); };
   loader.onprogress = loader.onloadstart = function (e) { def.notify(e); };
   loader.onerror = loader.onabort = function (e) { def.reject(e); };
   promise.abort = function () { return loader.abort.apply(loader, arguments); };

   loader.readAsBinaryString(file);

   return promise;
}

function upload(url, data){
    var def = $.Deferred(), promise = def.promise();
    var mul = buildMultipart(data);
    var req = $.ajax({
        url: url,
        data: mul.data,
        processData: false,
        type: "post",
        async: true,
        contentType: "multipart/form-data; boundary="+mul.bound,
        xhr: function() {
            var xhr = jQuery.ajaxSettings.xhr();
            if (xhr.upload) {

                xhr.upload.addEventListener('progress', function(event) {
                    var percent = 0;
                    var position = event.loaded || event.position; /*event.position is deprecated*/
                    var total = event.total;
                    if (event.lengthComputable) {
                        percent = Math.ceil(position / total * 100);
                        def.notify(percent);
                    }                    
                }, false);
            }
            return xhr;
        }
    });
    req.done(function(){ def.resolve.apply(def, arguments); })
       .fail(function(){ def.reject.apply(def, arguments); });

    promise.abort = function(){ return req.abort.apply(req, arguments); }

    return promise;
}

var buildMultipart = function(data){
    var key, crunks = [], bound = false;
    while (!bound) {
        bound = $.md5 ? $.md5(new Date().valueOf()) : (new Date().valueOf());
        for (key in data) if (~data[key].indexOf(bound)) { bound = false; continue; }
    }

    for (var key = 0, l = data.length; key < l; key++){
        if (typeof(data[key].value) !== "string") {
            crunks.push("--"+bound+"\r\n"+
                "Content-Disposition: form-data; name=\""+data[key].name+"\"; filename=\""+data[key].value[1]+"\"\r\n"+
                "Content-Type: application/octet-stream\r\n"+
                "Content-Transfer-Encoding: binary\r\n\r\n"+
                data[key].value[0]);
        }else{
            crunks.push("--"+bound+"\r\n"+
                "Content-Disposition: form-data; name=\""+data[key].name+"\"\r\n\r\n"+
                data[key].value);
        }
    }

    return {
        bound: bound,
        data: crunks.join("\r\n")+"\r\n--"+bound+"--"
    };
};

//----------
//---------- On submit form:
var form = $("form");
var $file = form.find("#file");
readFile($file[0].files[0]).done(function(fileData){
   var formData = form.find(":input:not('#file')").serializeArray();
   formData.file = [fileData, $file[0].files[0].name];
   upload(form.attr("action"), formData).done(function(){ alert("successfully uploaded!"); });
});

Z FormData API wystarczy dodać wszystkie pola formularza do obiektu FormData i wysłać je poprzez $.ajax({ url: url, data: formData, procesdata: false, contentType: false, type:"POST"})

 6
Author: Gheljenor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-29 07:36:04