我编写了一个脚本,它使用上传的excel文件将数据导入数据库。它首先检查图像是否可以下载,没有任何错误,然后插入其余的数据。有一万或十万行,这需要几个小时。有可能以某种方式使它更快吗?
= 400 && $http_code < 600 || $ssl === 1) {
return false;
}
try {
$stream = stream_context_create (array("ssl" => array("capture_peer_cert" => true)));
if(!empty($url)){
$read = @fopen($url, "rb", false, $stream);
if ($read !== false) {
$cont = @stream_context_get_params($read);
$ssl = ($cont["options"]["ssl"]);
fclose($read);
return (isset($ssl['peer_certificate']) && !is_null($ssl['peer_certificate'])) ? true : false;
} else {
return false;
}
}
}catch(ErrorException $e){
error_log($e->getMessage());
return false;
}
}
public function import($path)
{
$tempDirectoryName = 'temp';
$data = Excel::toArray([], $path);
$dataChunks = array_chunk($data[0], 25);
foreach ($dataChunks as $chunk) {
DB::beginTransaction();
foreach ($chunk as $row) {
if (!empty($row[3])) {
$valid = $this->checkURL($row[3]);
if ($valid === true) {
$video = Videos::with(['categories', 'stars', 'tags'])->where('url', $row[0])->first();
if (!$video) {
$slug = Str::slug($row[1], '-');
$i = 1;
while (Videos::where('slug', $slug)->exists()) {
$slug = Str::slug($row[1], '-') . '-' . $i;
$i++;
}
$video = Videos::create([
'url' => $row[0],
'title' => $row[1],
'slug' => $slug,
'length' => intval($row[2]),
'code' => intval($row[7]),
'embed_url' => $row[4],
'channel' => $row[9]
]);
}
try {
$media = $video->addMediaFromUrl($row[3])->toMediaCollection('video_index_images', 'public');
} catch (\Exception $e) {
Log::error("Error importing media for video ID {$video->id}: {$e->getMessage()}");
continue;
}
if (!$media && !$media->exists()) {
Log::error("Error importing media for video ID {$video->id}: Invalid media file");
continue;
}
$title = str_replace('_', ' ', $row[8]);
$slug = strtolower(str_replace(' ', '-', $title));
$title = ucfirst(strtolower($title));
$category = Categories::firstOrCreate(['title' => $title], ['slug' => $slug]);
$video->categories()->syncWithoutDetaching([$category->id]);
$names = explode(',', $row[6]);
foreach ($names as $name) {
$name = trim($name);
$name = str_replace('_', '', $name);
$slug = strtolower(str_replace(' ', '-', $name));
$star = Stars::firstOrCreate(['name' => $name], ['slug' => $slug]);
$video->stars()->syncWithoutDetaching([$star->id]);
}
$tags = explode(',', $row[5]);
$tagIds = [];
foreach ($tags as $tagName) {
$tagName = str_replace('-', ' ', trim($tagName));
if (!empty(trim($tagName))) {
$tag = Tags::firstOrCreate(['name' => $tagName, 'slug' => Str::slug($tagName)]);
$tagIds[] = $tag->id;
}
}
$video->tags()->detach();
$video->tags()->attach($tagIds);
$tempDirectory = storage_path('media-library/temp/'.$tempDirectoryName);
if (file_exists($tempDirectory)) {
\File::deleteDirectory($tempDirectory);
}
}
}
}
DB::commit();
}
}
} 我知道代码在循环中做了很多工作,但为了按预期工作,所有这些步骤都是必要的。
excel文件由10列组成:
该网站将是一个视频集合,所以外部媒体文件总是需要在上传时。一些索引图像的url丢失等等,这些视频不会被上传,这就是为什么我首先检查图像,然后才上传其余的。
使用以下操作在filamentphp资源文件中调用该脚本:
->actions([ Tables\Actions\Action::make('Run')
->icon('heroicon-o-play')
->requiresConfirmation()
->form([ FileUpload::make('excel')
->label('Excel')
->acceptedFileTypes(['application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet'])
->preserveFilenames(),])
->action(function ($data) {
$path = 'public/' . $data['excel'];
$importScript = new DataImport();
$importScript->import($path);
Storage::delete($path);
})
])发布于 2023-04-30 19:42:21
一些简短的评论:
checkURL是在循环中调用的,但在该函数中,每次都会关闭连接。相反,您可以通过reusing ( Curl句柄)来加快速度--打开一个新的连接会增加一些开销。另外,SSL协商中也存在开销。背景阅读https://codereview.stackexchange.com/questions/284560
复制相似问题