文章目录
前言
提示:我用的是laravel 框架 版本为6.20
实现这个功能所需要的插件有
1、laravel Excel 3.1 (读取excel文件所需) 官方手册(https://docs.laravel-excel.com/3.1/getting-started/)
一、需求解析
刚开始拿到这个需求肯定是解析需求。
这个功能大概能分为四个步骤:
1、上传文件
2、解压压缩包
3、读取解压后文件目录
4、识别excel并自动添加
二、上传文件
代码如下(示例):
//这里只支持zip 其他文件类型的可以自己添加
public function uploadFile(Request $request){
if ($request->hasFile('file') && $request->file('file')->isValid()) {
$file = $request->file('file');
$file_name1 = $file->getClientOriginalName();
$allowed_extensions = [
"zip",
];
if (!in_array($file->getClientOriginalExtension(), $allowed_extensions)) {
return $this->fail('文件格式不在限制范围内', [
'file_type' => $file->getClientOriginalExtension()
]);
// dd('只能上传png,jpg和gif格式的图片.');
} else {
$destinationPath = "storage/uploads/Fei-Yong-Xiang-Qing-Dan/" . date('Y') . '/' . date('m-d') . '/'; //public 文件夹下面建 storage/uploads 文件夹
$extension = $file->getClientOriginalExtension();
$fileSize = $file->getSize();
$tmpstr = md5(time() . rand(1, 1000)) ;
$fileName = $tmpstr. '.'.$extension;
$file->move($destinationPath, $fileName);
$filePath = asset($destinationPath . $fileName);
/*---*/
//获取文件类型
$fileType = $file->getClientOriginalExtension();
return $this->success('导入解析成功', [
'file_path' => $destinationPath . $fileName,
'file_type' => $fileType,
'file_size' => $fileSize,
'file_name'=>$file_name1,
]);
}
}
}
方法内使用的公共方法
/**
* $msg 返回提示消息
* $data 返回数据
*/
public function success($msg='执行成功',$data = [])
{
return response()->json([
'status' => true,
'code' => 200,
'msg' => $msg??'执行成功',
'data' => $data,
]);
}
/**
* $msg 返回提示消息
* $data 返回数据
*/
public function fail($msg='执行失败',$data = [])
{
return response()->json([
'status' => false,
'code' => -1000,
'msg' => $msg??'执行失败',
'data' => $data,
]);
}
三、解压压缩包
解压压缩包PHP有好多方法,我这里用的是PHP内置自带的类 ZipArchive。
代码如下(示例):
/**
* @content 解压压缩包
* @param $file_path 源文件的文件地址
* @param $myFileName 解压后的文件地址
* @return string 返回解压后文件所在位置
* @throws \Exception
* $this->unzip('/public/源文件.zip','/public/解压后文件/解压文件.zip')
*/
public function unzip($file_path,$myFileName){
$fileSavePath = storage_path().'/app/public/uploads/Fei-Yong-Xiang-Qing-Dan-Jie-Ya/'. date('Y') . '/' . date('m-d') . '/'.$myFileName;
$zipName =public_path().'/'.$file_path;
$zip = new \ZipArchive();
$res = $zip->open($zipName);
if ($res !== true){
throw new \Exception('打开压缩包失败');
}
//var_dump(\ZipArchive::FL_ENC_RAW);
$fileNum = $zip->numFiles;
for ($i = 0; $i < $fileNum; $i++) {
$statInfo = $zip->statIndex($i,\ZipArchive::FL_ENC_RAW);
$newfilename = mb_convert_encoding($statInfo['name'],'UTF-8','GBK');// ,'UTF-8','GBK' 仅支持nginx 系统的
$zip->renameIndex($i, $newfilename);
}
$zip->close();
$zip->open($zipName);
$zip->extractTo($fileSavePath);
$zip->close();
return $fileSavePath;
}
警告注意:
1、PHP在解压文件后若文件内的目录为中文目录则会有编码不对应得问题 所以需要 mb_convert_encoding 这个方法 但是这个方法因为系统的原因导致编码不一样从而引起转码后编码出错的问题就像下图。所以这块要根据文件和系统进行转码。
2、在PHP解压过一次以后的文件不能进行第二次解压。因为在上面就压有已经更改了他的编码方式,如果在进行第二次解压的话就会乱码,无法转为中文。这里踩坑踩了一天,一直认为值我后续解压代码的问题
四、读取解压后的文件目录
这里有两个方法,根据自己的需求拿
方法一、
/**
* @content 获取文件夹下,一个文件的名称
* @param $path
* @return bool|string
* 比如: /d/a文件/b文件 则 $this->getFileName('/d/a文件'); 返回 :/d/a文件/b文件
*/
public function getFileName($path)
{
$file_name = '';
$info = opendir($path);
while (($file = readdir($info)) !== false) {
if( $file != "." && $file != ".." && strpos($file,'.xlsx') == false){
$file_name = $file;
}
}
return $file_name;
}
方法二、
/**
* @content 获取文件名称
* @param $path @文件地址
* @param $finename @空数组 返回用
* $finename = [];
* $file_path = '/d/a文件/b文件';
* $this->getFiles($file_path,$finename); 返回 b文件夹呢呢所有文件,直到找到最底层
* [
* file_name=>"a文件"
* file_path=>"/d/a文件/b文件"
* child=>[
* file_name=>"c文件.excel"
* file_path=>"/d/a文件/b文件/c文件.excel"
* ]
* 。。。。。
* ]
*/
public function getFiles($path,&$finename)
{
$info = opendir($path);
$tmpPath = base_path().'/';
while (($file = readdir($info)) !== false) {
if( is_dir($path.'/'.$file) && $file != "." && $file != ".."){
$tmpArr = [];
$tmpArr['file_name'] = $file;
$tmpPathOne = explode($tmpPath, $path);
$tmpArr['file_path'] = $tmpPathOne[1].'/'.$file;
$finename[$file] = $tmpArr;
unset($tmpArr);
$this->getFiles($path.'/'.$file,$finename[$file]['child']);
}elseif($file != "." && $file != ".."){
$tmpArr = [];
$tmpArr['file_name'] = $file;
$tmpPathOne = explode($tmpPath, $path);
$tmpArr['file_path'] = $tmpPathOne[1].'/'.$file;
$finename[$file] = $tmpArr;
unset($tmpArr);
}
}
}
读取excel文件
1、 安装laravel excel 3.1 如果已经安装了那就跳过此步
1、在项目根目录下运行命令
composer require maatwebsite/excel
2、注册 在文件config/app.php下
'providers' => [
/*
* Package Service Providers...
*/
Maatwebsite\Excel\ExcelServiceProvider::class,
]
'aliases' => [
...
'Excel' => Maatwebsite\Excel\Facades\Excel::class,
]
3、生成配置文件与 config 文件下
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
2、解析excel文件并实现添加
1、生成imports 导入文件类
php artisan make:import demoImporst
生成的文件位于 app/Imports 下
2、重写import 文件 //值得注意的是这个文件内的执行会有事务
<?php
namespace App\Imports;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use App\Http\Models\Admin;
class demoImporst implements ToCollection
{
/**
* @param Collection $collection
*/
public function collection(Collection $collection)
{
$data = $collection->toArray();
foreach($data as $key=>$value){
$tmpData = [];
$tmpData['name'] =>$value[0];
$tmpData['value'] =>$value[1];
$tmoData['created_at'] =>time();
$tmoData['updated_at'] =>time();
Admin::insert($tmoData);
}
}
}
3、调用方法
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\demoImporst;
class demo
{
public function demo1()
{
$tmpExcelFilePath = '/d/a文件/c文件/a.xlsx'
Excel::import(new demoImporst(), $tmpExcelFilePath);
}
}