簡體   English   中英

使用 html5、javascript 和 PHP 分塊上傳文件

[英]uploading a file in chunks using html5 , javascript and PHP

基本上我必須逐塊上傳文件,因為文件非常大,我嘗試使用此解決方案使用 html5 分塊上傳文件,但文件已損壞,因為重建的文件不按順序排列。

我試圖實現鏈接中給出的答案,但我真的很困惑如何在我的 php 頁面和我的 html 頁面上實現它。 如果你們能給我一個建議或方法,那就太好了。 感謝您的時間。

編碼:

上傳.php

 <?php 

    $target_path = "/home/imagesdcard/www/";
    $tmp_name = $_FILES['fileToUpload']['tmp_name'];
    $size = $_FILES['fileToUpload']['size'];
    $name = $_FILES['fileToUpload']['name'];


    $target_file = $target_path . basename($name);
    $complete = "test.txt";
    $com = fopen("/home/imagesdcard/www/".$complete, "ab");
    error_log($target_path);

    // Open temp file
    $out = fopen($target_file, "wb");

    if ( $out ) {
        // Read binary input stream and append it to temp file
        $in = fopen($tmp_name, "rb");
        if ( $in ) {
            while ( $buff = fread( $in, 1024) ) {
            fwrite($out, $buff);
            fwrite($com, $buff);
        }   
    }
    fclose($in);
    fclose($out);
}
fclose($com);

?>

html

<!DOCTYPE html>
<html>
    <head>
        <title>Upload Files using XMLHttpRequest</title>
        <script type="text/javascript">

            window.BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder;

            function sendRequest() {
                var blob = document.getElementById('fileToUpload').files[0];
                const BYTES_PER_CHUNK = 1048576; // 1MB chunk sizes.
                const SIZE = blob.size;
                var i=0;
                var start = 0;
                var end = BYTES_PER_CHUNK;
                while( start < SIZE ) {
                    var chunk = blob.slice(start, end);
                    uploadFile(chunk,i);
                    i++;
                    start = end;
                    end = start + BYTES_PER_CHUNK;
                }
            }

            function fileSelected() {
                var file = document.getElementById('fileToUpload').files[0];
                if (file) {
                    var fileSize = 0;
                    if (file.size > 1024 * 1024)
                        fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
                    else
                        fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';

                    document.getElementById('fileName').innerHTML = 'Name: ' + file.name;
                    document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;
                    document.getElementById('fileType').innerHTML = 'Type: ' + file.type;
                }
            }

            function uploadFile(blobFile,part) {
                //var file = document.getElementById('fileToUpload').files[0];  
                var fd = new FormData();
                fd.append("fileToUpload", blobFile);

                var xhr = new XMLHttpRequest();
                xhr.upload.addEventListener("progress", uploadProgress, false);
                xhr.addEventListener("load", uploadComplete, false);
                xhr.addEventListener("error", uploadFailed, false);
                xhr.addEventListener("abort", uploadCanceled, false);
                xhr.open("POST", "upload.php?num="+part);
                xhr.onload = function(e) {
                  alert("loaded!");
                  };

                xhr.send(fd);
                //alert("oen over");
            }

            function uploadProgress(evt) {
                if (evt.lengthComputable) {
                    var percentComplete = Math.round(evt.loaded * 100 / evt.total);
                    document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
                }
                else {
                    document.getElementById('progressNumber').innerHTML = 'unable to compute';
                }
            }

            function uploadComplete(evt) {
                /* This event is raised when the server send back a response */
                alert(evt.target.responseText);
            }

            function uploadFailed(evt) {
                alert("There was an error attempting to upload the file.");
            }

            function uploadCanceled(evt) {
                xhr.abort();
                xhr = null;
                //alert("The upload has been canceled by the user or the browser dropped the connection.");
            }
        </script>
    </head>
    <body>
        <form id="form1" enctype="multipart/form-data" method="post" action="upload.php">
            <div class="row">
                <label for="fileToUpload">Select a File to Upload</label><br />
                <input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();"/>
                <input type="button" value="cancel"  onClick="uploadCanceled();"/>
            </div>
            <div id="fileName"></div>
            <div id="fileSize"></div>
            <div id="fileType"></div>
            <div class="row">
                <input type="button" onclick="sendRequest();" value="Upload" />
            </div>
            <div id="progressNumber"></div>
        </form>
    </body>
</html>

您的腳本不起作用,因為 js 是異步的。 您應該將代碼更改為:

xhr.open("POST", "upload.php?num="+part, false);

和文件保存正常。

我按塊上傳大文件的解決方案。

上傳.php (php部分)

<?php
    session_start();
    
    if($_SERVER["REQUEST_METHOD"] == "POST")
    {
        $chunk = $_FILES["chunk"]["tmp_name"];
        $filename = $_POST['filename'];
    
        if(!isset($_SESSION[$filename]))
        {
            $_SESSION[$filename] = tempnam(sys_get_temp_dir(), 'upl');
        }
    
        $tmpfile = $_SESSION[$filename];
    
        if(isset($chunk))
        {
            file_put_contents($tmpfile, file_get_contents($chunk), FILE_APPEND);
        }
        else
        {
            rename($tmpfile, $filename);
        }
        exit();
    }
?>

upload.php (html\js 部分)

<!DOCTYPE html>
<html>
    <head>
        <title>Upload Files using XMLHttpRequest</title>
        <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
        <script type="text/javascript">
            function sendRequest() {
                // 1MB chunk sizes.
                var chunk_size = 1048570;
                var file = document.getElementById('file').files[0];
                var filesize = file.size;
                var filename = file.name;
                var pos = 0;
                while(pos < filesize) {
                    let chunk = file.slice(pos, pos+chunk_size);
                    pos += chunk_size;

                    var data = new FormData();
                    data.append('chunk', chunk);
                    data.append('filename', filename);

                    $.ajax({url:'upload.php',type: 'post',async:false,data: data,processData: false,contentType: false});

                    let percentComplete = Math.round(pos * 100 / filesize);
                    document.getElementById('progressNumber').innerHTML = (percentComplete > 100 ? 100 : percentComplete) + '%';
                }
                $.post('upload.php',{filename:filename});
            }
        </script>
    </head>
    <body>
        <form>
            <div class="row">
                <label for="file">Select a File to Upload</label><br />
                <input type="file" name="file" id="file" onchange="sendRequest();"/>
            </div>
            <div id="progressNumber"></div>
        </form>
    </body>
</html>

但此代碼有一個錯誤 - 進度條在 chrome 中不起作用,僅在 firefox 中起作用。

如果您想在 chrome 瀏覽器中工作,您應該發出異步請求並發出遞歸 function,例如: upload.php (PHP)

<?php
session_start();
$chunk_size = 1048570;
if($_SERVER["REQUEST_METHOD"] == "POST")
{
    header("Content-type: application/json; charset=UTF-8");
    header("Cache-Control: must-revalidate");
    header("Pragma: no-cache");
    header("Expires: -1");

    $filename = $_POST["filename"];
    $chunk = $_FILES["chunk"]["tmp_name"];
    $from = intval($_POST["from"]);
    $upload = new stdClass();

    if(!isset($_SESSION[$filename]))
        $_SESSION[$filename] = tempnam(sys_get_temp_dir(), 'upl');

    $tmpfile = $_SESSION[$filename];

    if(isset($chunk))
        file_put_contents($tmpfile, file_get_contents($chunk), FILE_APPEND);

    $upload->from = $from + $chunk_size;
    $upload->filesize = $_POST['filesize'];
    $upload->filename = $filename;

    if($upload->from >= $upload->filesize)
    {
        rename($tmpfile, "test.file");
        unset($_SESSION[$filename]);
    }

    print json_encode($upload);
    exit();
}

上傳.php (HTML\JS)

<!DOCTYPE html>
<html>
    <head>
        <title>Upload Files using XMLHttpRequest</title>
        <script src="https://code.jquery.com/jquery-3.6.0.js"></script>

        <script type="text/javascript">
        var chunk_size = '<?php echo $chunk_size; ?>';
        function do_request(from)
        {
            var file = $("#file").get(0).files[0];

            var data = new FormData();
            data.append('chunk', file.slice(from, from+chunk_size));
            data.append('filename', file.name);
            data.append('filesize', file.size);
            data.append('from', from);

            $.ajax({
                url: "upload.php", type: "post", data:data, processData:false, contentType:false, dataType: 'json',
                success: function(data)
                {
                    $("#progress").val((data.from / data.filesize) * 100);
                    if(data.from < data.filesize)
                        do_request(data.from);
                }
            });
        }
        </script>
    </head>
    <body>
        <form>
            <div class="row">
                <label for="file">Select a File to Upload</label><br />
                <input type="file" name="file" id="file" onchange="do_request(0);"/>
            </div>
            <progress id="progress" min="0" max="100" value="0"></progress>
        </form>
    </body>
</html>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM