一、编写前端简单上传的 html 与 jquery
在 Laravel 框架的 resources/views 目录下创建:upload.blade.php 文件,下面介绍该文件的内容。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajax上传文件进度条显示</title>
<script type="text/javascript">
function sendfile(){
const LENGTH=5*1024*1024;//定义一次上传多少 这里是 5M 一次
var sta=0;
var end=sta+LENGTH;
var blob=new Blob();
var fd=null;
var xhr=null;
var pic=document.getElementsByTagName('input')[0].files[0];
//console.log(pic);
var name=pic.name;
var totalsize=pic.size;
var precent=null;
while(sta<totalsize){
blob=pic.slice(sta,end);
xhr=new XMLHttpRequest();
xhr.open('POST','{{ route('upload.store') }}',false);//上传的路由地址 upload.store 在下面路由创建有说明
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);//进度
if(precent>=100){
precent=100;
}
console.log(Math.round(precent)+'%');//在console看进度完成率
document.getElementById('nei').style.width=precent + '%';
document.getElementById('precent').innerHTML=Math.floor(precent)+'%';
sta=end;
end=end+LENGTH;
}
}
</script>
<style>
#wai{
width:500px;
height:30px;
border:1px solid green;
}
#nei{
width:0px;
height:30px;
background:green;
}
</style>
</head>
<body>
<div id="wai">
<div id="nei"></div>
</div>
<span id="precent"></span><br/>
<input type="file" name="pic" /><br/><br/>
<input type="submit" value="提交" onclick="sendfile();"/>
</body>
</html>
二、创建接口,进行约束
在 laravel 框架 app 的目录下创建:Contracts 目录以及 UploadContracts.php 接口文件;以下是接口文件内容。
<?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();
}
三、创建工具类进行接口的使用
在 laravel 框架 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; //接收文件对象
protected $fileName;//文件名称
protected $fileSize;//文件大小
protected $fileExtension;//文件拓展名
protected $fileImage = [ //图片的限制
'png','jpg','jpeg','gif'
];
protected $fileTxt = [ //文件的限制
'docx','doc','txt','csv','pdf','xlsx','xls','ppt','pptx','rtf'
];
protected $url = 'default'; //如果匹配不到上面的图片后缀和文件后缀,就上传到这个目录
protected $pathUrl;//上传的地址
public function requestFile(Request $request)
{
$this->file = $request->file('part');//前端提交过来的
$this->fileName = $request->input('name');//前端提交过来的
$this->fileSize = $this->file->getSize();//获取文件大小
$this->fileExtension = $this->file->extension();//获取文件的拓展名
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);
}
}
四、创建 Controller 进行使用文件上传接口的功能
在 laravel 框架的 app/Http/Controllers 的目录下创建 UploadController.php 文件,下面是该文件内容。
<?php
namespace App\Http\Controllers;
use App\Contracts\UploadContracts;//引用接口文件
use Illuminate\Http\Request;//引用Request功能
class UploadController extends Controller
{
public function store(Request $request,UploadContracts $uploadContracts){
//把上传的文件传送到接口类里面,然后工具类里面进行校验
$upload = $uploadContracts->requestFile($request);
//文件校验
$upload->FileCheck();
//文件上传
$upload->UploadFile();
//上传后返回信息
return response()->json([
'code' => 200,
'info' => '上传成功'
]);
}
}
五、定义路由
laravel 框架里面不定义路由是不能访问的。路由文件:routes/web.php
<?php
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
//默认路由
Route::get('/', function () {
return view('welcome');
});
//定义的前端路由
Route::view('upload','upload');
//定义文件上传的路由 这是8版本以上的写法 any代表允许任何方式访问
Route::any('UploadFile',[ App\Http\Controllers\UploadController::class,'store'])->name('upload.store');
//name 前端使用的路由名,实则访问的路由是 UploadFile
六、跳过路由校验
为什么要跳过路由的校验呢?
因为,不跳过校验的话,会报出一个 419 的错误。
419错误解释:服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突。
跟多状态码请看这个:HTTP状态码 | 菜鸟教程
回到正题;跳过路由的中间件在:app/Http/Middleware/VerifyCsrfToken.php
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
'UploadFile' //将刚才定义的路由名称加入进来,跳过检测
];
}
七、注册契约
如果没有注册的接口或契约的话,是无法使用的;会报出 500 的状态码。
注册文件:app/Providers/AppServiceProvider.php
<?php
namespace App\Providers;
use App\Contracts\UploadContracts;//引入接口类
use App\Support\UploadSupport;//引入工具类
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//注册接口类
$this->app->singleton(UploadContracts::class,UploadSupport::class);
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
}
到此就结束了,访问前端路径,上传一下即可。