PHP 实现解压excel压缩包并识别压缩包内的excel文件 实现内容批量添加


前言

提示:我用的是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); 
	}

}

可以使用 Java ZipInputStream 类和 ZipEntry 类来实现解压文件,然后再结合上面的获取多层文件夹内所有 Excel 文件的方法,就可以实现获取压缩包内多层文件的所有 Excel 文件了。下面是示例代码: ```java import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class ZipFileExtractor { public static void main(String[] args) { String zipFilePath = "C:\\path\\to\\file.zip"; String destFolderPath = "C:\\path\\to\\destination\\folder"; extractZipFile(zipFilePath, destFolderPath); getExcelFiles(destFolderPath); } public static void extractZipFile(String zipFilePath, String destFolderPath) { byte[] buffer = new byte[1024]; try { // 创建目标文件夹 File destFolder = new File(destFolderPath); if (!destFolder.exists()) { destFolder.mkdir(); } // 打开压缩文件 ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFilePath)); // 解压文件 ZipEntry zipEntry; while ((zipEntry = zipInputStream.getNextEntry()) != null) { String fileName = zipEntry.getName(); File newFile = new File(destFolderPath + File.separator + fileName); if (zipEntry.isDirectory()) { newFile.mkdirs(); } else { // 创建父文件夹 newFile.getParentFile().mkdirs(); // 写入文件 FileOutputStream fileOutputStream = new FileOutputStream(newFile); int len; while ((len = zipInputStream.read(buffer)) > 0) { fileOutputStream.write(buffer, 0, len); } fileOutputStream.close(); } zipInputStream.closeEntry(); } zipInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } public static void getExcelFiles(String folderPath) { // 与上一个问题的代码相同 } } ``` 在 `extractZipFile` 方法,首先创建目标文件夹,然后遍历压缩包内的所有文件文件夹,如果是文件夹则创建对应的文件夹,如果是文件则将其解压到目标文件。最后调用 `getExcelFiles` 方法即可获取目标文件夹内多层文件的所有 Excel 文件
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值