laravel 分片上传

<input type="hidden" id="aid" name="aid">
<span class="input-group-text" id="upload-btn"></span>
<div class="p-4">
    <div class="alert alert-warning">{{ __('请上传压缩包文件') }},仅支持.zip,100MB以内。</div>
    <div class="mb-3">
        <input type="file" class="form-control w-auto" accept=".zip" id="attach">
    </div>
    <div class="mb-3">
        <input type="text" class="form-control" id="description" placeholder="文件描述">
    </div>
    <div class="progress mb-3">
        <div class="progress-bar bg-success" id="upload-progress" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
    </div>
    <button class="btn btn-primary px-4" role="button" onclick="sendfile();">上传</button>
</div>
<script type="text/javascript">
function sendfile(){
    const LENGTH = 2 * 1024*1024;//定义一次上传多少 这里是 5M 一次
    var sta = 0;
    var end = sta+LENGTH;
    var blob = new Blob();
    var fd = null;
    var xhr = null;
    var xhs = null;
    
    var loadingText = '上传中';
    var attach = document.getElementById('attach').files[0];
    if(!attach){
        document.getElementById('upload-progress').style.width = '0%';
        alert('没有选择文件');
        return false;
    }
    var name = attach.name;
    var totalsize = attach.size;

    var precent = null;
    while(sta < totalsize){
        blob = attach.slice(sta,end);
        xhr = new XMLHttpRequest();
        xhr.open('POST','{{ route('upload.store') }}',false);
        fd = new FormData();
        fd.append('part',blob);
        fd.append('name',name);
        xhr.send(fd);

        var response = JSON.parse(xhr.responseText);
        if (response.code == 422){
            alert(response.error);
            break;
        }
        precent = 100 * (end/totalsize);
        document.getElementById('upload-progress').style.width=precent + '%';
        document.getElementById('upload-progress').innerHTML=Math.floor(precent) + '%' + '-'+loadingText;
        if(precent >= 100){
            precent = 100;
            loadingText = response.info;
            var file = document.getElementById('attach');
            if(file.outerHTML){
                file.outerHTML = file.outerHTML;
            }else{
                file.value="";
            }
            xhs = new XMLHttpRequest();
            xhs.open('POST','{{ route('upload.save') }}',false);
            data = new FormData();
            data.append('path', response.path);
            data.append('filename', response.filename);
            data.append('filesize', response.filesize);
            data.append('description', document.getElementById('description').value);
            xhs.send(data);
            var res = JSON.parse(xhs.responseText);
            if(res.code == 200){
                loadingText = res.info;
                document.getElementById('aid').value = res.aid;
                document.getElementById('upload-btn').innerHTML = response.filename;
            }
        }

        sta = end;
        end = end+LENGTH;
    }
}
</script>

控制器

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Contracts\UploadContracts;
use App\Models\Attachment;

class FileController extends Controller
{
    public function store(Request $request, UploadContracts $uploadContracts)
    {
        $upload = $uploadContracts->requestFile($request); //把上传的文件传送到接口类里面,然后工具类里面进行校验
        $upload->FileCheck(); //文件校验
        $upload->UploadFile(); //文件上传
        $savePath = '/'.$upload->url.'/'.$upload->fileName;
        return response()->json(['code' => 200, 'info' => '上传成功', 'path' => $savePath, 'filename'=>$upload->fileName]);
    }
    
    public function save(Request $request)
    {
        $filepath = storage_path('app/public'.$request->path);
        $extension = pathinfo($filepath, PATHINFO_EXTENSION);
        $newPath = Auth::user()->id.'_'.uniqid().'.'.$extension;
        $savePath = public_path('uploads/files/'.$newPath);
        rename($filepath, $savePath);
        
        $attachment = new Attachment;
        $attachment->path = '/uploads/files/'.$newPath;
        $attachment->user_id = Auth::user()->id;
        $attachment->filename = $request->filename;
        $attachment->description = $request->description;
        $attachment->filesize = filesize($savePath);
        $attachment->save();
        
        if($attachment){
            return response()->json(['code' => 200, 'info' => '保存成功', 'aid' => $attachment->id]);
        }
    }
    
    public function add(Request $request)
    {
        return view('file.add');
    }

    public function manage(Request $request)
    {
        $myattachments = Auth::user()->attachments()->paginate(30);
        return view('file.manage', compact('myattachments'));
    }
}

app\Contracts\UploadContracts

<?php
 
namespace App\Contracts;

use Illuminate\Http\Request;

interface UploadContracts
{

    /**
     * @param Request $request
     * @return mixed
     * 接收文件
     */
    public function requestFile(Request $request);
 
 
    /**
     * @return mixed
     * 文件校验
     */
    public function FileCheck();
 
 
    /**
     * @return mixed
     * 判断目录是否存在
     */
    public function ExistsDir();
 
 
    /**
     * @return mixed
     * 上传文件
     */
    public function UploadFile();

}

app\Support\UploadSupport.php

<?php
 
namespace App\Support;
 
use App\Contracts\UploadContracts; //引入接口
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;//引入目录类
 
class UploadSupport implements UploadContracts
{
 
    protected $file; //接收文件对象
 
    public $fileName;//文件名称
 
    public $fileSize;//文件大小
 
    protected $fileExtension;//文件拓展名
 
    protected $fileImage = [ //图片的限制
        'png','jpg','jpeg','gif'
    ];
 
    protected $fileTxt = [ //文件的限制
        'docx','doc','txt','csv','pdf','xlsx','xls','ppt','pptx','rtf'
    ];
 
    public $url = 'default'; //如果匹配不到上面的图片后缀和文件后缀,就上传到这个目录
 
    protected $pathUrl;//上传的地址
 
 
    public function requestFile(Request $request)
    {
        $this->file = $request->file('part');//前端提交过来的
        $this->fileSize = $this->file->getSize();//获取文件大小
        $this->fileExtension = $this->file->extension();//获取文件的拓展名
        $this->fileName = $request->input('name');//前端提交过来的
        return $this;
    }
 
 
    public function FileCheck()
    {
        //判断是否为图片
        if(in_array($this->fileExtension,$this->fileImage)){
            $this->url = 'images';
        }
 
        //判断是否为txt类文件
        if(in_array($this->fileExtension,$this->fileTxt)){
            $this->url = 'document';
        }
 
        //检测文件目录是否存在
        $this->ExistsDir();
 
        //上传的路径
        $this->pathUrl = Storage::path('public').'/'.$this->url.'/'.$this->fileName;
 
        //返回当前内容
        return $this;
    }
 
 
    public function ExistsDir()
    {
        //Storage 是laravel框架自带的目录类,Storage::path('public')它的目录是在:storage/app/public
        //判断目录是否存在
        if(!is_dir(Storage::path('public').'/'.$this->url)){
            //不存在就创建
            mkdir(Storage::path('public').'/'.$this->url);
        }
        //返回true
        return true;
    }
 
 
    public function UploadFile()
    {
        //判断上传的文件是否存在
        if(!file_exists($this->pathUrl)){
            return move_uploaded_file($this->file->path(),$this->pathUrl);
        }
        //上传操作
        return file_put_contents($this->pathUrl,file_get_contents($this->file->path()),FILE_APPEND);
    }
}
相关文章