首页 > 解决方案 > 通过javascript将大文件上传到服务器

问题描述

使用 javascript 和 ajax 将任何类型的技嘉文件(例如:视频、音频、图像、文档)上传到 php 服务器的最佳方式是什么?

将文件作为分块 blob发送?

还是先将blob转换为ArrayBuffer然后发送到 php?

将文件作为 ArrayBuffer发送时如何在服务器端合并文件?

文件到blob函数:

function sliceFile(file, chunksAmount) {
var byteIndex = 0;
var chunks = [];
for (var i = 0; i < chunksAmount; i += 1) {
var byteEnd = Math.ceil((file.size / chunksAmount) * (i + 1));
chunks.push(file.slice(byteIndex, byteEnd));
byteIndex += (byteEnd - byteIndex);
}

return chunks;

}

作为ArrayBuffer函数发送:

function sendChunkFile(chunksArray,filename){
var slice_chunk = chunksArray.shift();
var reader = new FileReader();
reader.onload = function(event){
        var fd = new FormData();
        fd.append('filename', filename);
        fd.append('data', event.target.result);
        $.ajax({
            type: 'POST',
            url: 'upload.php',
            data: fd,
            processData: false,
            contentType: false
        }).done(function(data) {
            if(chunksArray.length){
            sendChunkFile(chunksArray,filename)
            }
        });
    };      
    reader.readAsArrayBuffer(slice_chunk);
}

标签: javascriptphpfile-uploadblobarraybuffer

解决方案


客户端

步骤1 :

制作Blob 切片

切片功能

function slice(file, start, end) {
 var slice = file.mozSlice ? file.mozSlice :
          file.webkitSlice ? file.webkitSlice :
          file.slice;

 return slice.bind(file)(start, end);
}

文件切片器

 function sliceFile(file, chunksAmount, mimetype) {
 var byteIndex = 0;
 var chunks = [];

 for (var i = 0; i < chunksAmount; i += 1) {
var byteEnd = Math.ceil((file.size / chunksAmount) * (i + 1));
chunks.push( new Blob([slice(file, byteIndex, byteEnd)], {
type: mimetype
  }));

   byteIndex += (byteEnd - byteIndex);
}

  return chunks;
}

文件切片器助手

function chunksAmount(size){
const BYTES_PER_CHUNK = ((1024 * 1024)*5); //5MB chunk sizes.
return Math.ceil(size / BYTES_PER_CHUNK);
}

获取 Blob

var file = self.get(0).files.item(0); //files[0];
var chunks = chunksAmount(file.size);
var blobChunksArray = sliceFile(file,chunks,file.type);

第2步 :

Blob发送到服务器端

发送功能

function sendChunkFile(chunksArray,filename){
var slice_chunk = chunksArray.shift();

    var fd = new FormData();
    fd.append('chunksupload',true);
    fd.append('filename', filename);
    fd.append('data', slice_chunk);
    if(chunksArray.length){
    fd.append('chunksend',false);
    }else{
    fd.append('chunksend',true);
    }
    $.ajax({
        type: 'POST',
        url: 'upload.php',
        data: fd,
        processData: false,
        contentType: false
    }).done(function(data) {
        if(chunksArray.length){
        sendChunkFile2(chunksArray,filename)
        }else{
        console.log(JSON.stringify(data));
        }
    });

}

第 3 步:

通过PHP处理Blob服务器端

<?php
if(isset($_POST['chunksupload'])){

file_put_contents($_POST['filename'], file_get_contents($_FILES['data']['tmp_name']), FILE_APPEND | LOCK_EX);

if($_POST['chunksend']){
    echo json_encode(["url"=>"path-to-file/".$_POST['filename'],"size"=>filesize($_POST['filename']) . " bytes"]);
}else{
    return true;
}
}
return false;

推荐阅读