Spring Boot中前端通过请求接口下载后端存放的Excel模板

news2024/11/20 15:40:42

导出工具类

package com.yutu.garden.utils;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import org.apache.commons.io.IOUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * @ClassName: ExcelUtils
 * @Description: Excel相关操作
 * @Author
 * @Date 2022/4/11
 * @Version 1.0
 */
@Component
public class ExcelUtils {

	@Resource
	private  ResourceLoader resourceLoader;
	private static Logger log = LoggerFactory.getLogger(ExcelUtils.class);
	static{
		System.setProperty("java.awt.headless", "true");
	}

	/**
	 * 设置表头
	 * @param sheet sheet
	 * @param str 表头数据
	 * @param startNum 开始行
	 * @param height 高度
	 * @param style 样式
	 */
	public static void setTitle(HSSFSheet sheet, String[] str,int startNum,Short height,HSSFCellStyle style,Integer[] widths,int width) {
		try {
			HSSFRow row = sheet.createRow(startNum);
			if(ObjectUtils.isEmpty(height)){
				height = (short)(20*20);
			}
			row.setHeight(height);
			//创建表头名称
			HSSFCell cell;
			for (int j = 0; j < str.length; j++) {
				cell = row.createCell(j);

				//设置列宽,setColumnWidth的第二个参数要乘以256,这个参数的单位是1/256个字符宽度
				if(ObjectUtils.isNotEmpty(widths) && ObjectUtils.isNotEmpty(widths[j]) ){
					sheet.setColumnWidth(j, widths[j]);
				}else{
					sheet.autoSizeColumn(j);
					int colWidth = sheet.getColumnWidth(j) * width / 10;
//					if (colWidth > 255) {
//						colWidth = 255;
//					}

					sheet.setColumnWidth(j, colWidth);
				}

				cell.setCellValue(str[j]);
				cell.setCellStyle(style);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void setTitle(HSSFSheet sheet, List<String> str,int startNum,Short height,HSSFCellStyle style,Integer[] widths) {
		try {
			HSSFRow row = sheet.createRow(startNum);
			if(ObjectUtils.isEmpty(height)){
				height = (short)(20*20);
			}
			row.setHeight(height);
			//创建表头名称
			HSSFCell cell;
			for (int j = 0; j < str.size(); j++) {
				cell = row.createCell(j);

				//设置列宽,setColumnWidth的第二个参数要乘以256,这个参数的单位是1/256个字符宽度
				if(ObjectUtils.isNotEmpty(widths) && ObjectUtils.isNotEmpty(widths[j]) ){
					sheet.setColumnWidth(j, widths[j]);
				}else{
					sheet.autoSizeColumn(j);
					sheet.setColumnWidth(j, sheet.getColumnWidth(j) * 30 / 10);
				}

				cell.setCellValue(str.get(j));
				cell.setCellStyle(style);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 方法名:setData
	 * 功能:表格赋值
	 */
	public static void setData(HSSFSheet sheet, List<Object[]> data,int startNum,HSSFCellStyle style) {
		try{
			int rowNum = startNum+1;
			for (int i = 0; i < data.size(); i++) {
				HSSFRow row = sheet.createRow(rowNum);
				for (int j = 0; j < data.get(i).length; j++) {
					HSSFCell cell = row.createCell(j);
					if(ObjectUtils.isEmpty(data.get(i)[j])){
						cell.setCellValue("");
					}else{
						cell.setCellValue(data.get(i)[j].toString());
					}
					cell.setCellStyle(style);
				}
				rowNum++;
			}
		}catch (Exception e){
			e.printStackTrace();
		}
	}

	public static void setDataByList(HSSFSheet sheet, List<List<Object>> data,int startNum) {
		try{
			int rowNum = startNum+1;
			for (int i = 0; i < data.size(); i++) {
				HSSFRow row = sheet.createRow(rowNum);

				for (int j = 0; j < data.get(i).size(); j++) {
					if(ObjectUtils.isEmpty(data.get(i).get(j))){
						row.createCell(j).setCellValue("");
					}else{
						row.createCell(j).setCellValue(data.get(i).get(j).toString());
					}
				}
				rowNum++;
			}
		}catch (Exception e){
			e.printStackTrace();
		}
	}

	/**
	 * 方法名:setBrowser
	 * 功能:使用浏览器下载
	 */
	public static void setBrowser(HttpServletResponse response, HSSFWorkbook workbook, String fileName) {
		try {
			//清空response
			//response.reset();
			//设置response的Header
			String name = URLEncoder.encode(fileName, "UTF-8");
			//Content-disposition 的 attachment参数将文件作为附件下载
			//response.setHeader("Content-disposition", "attachment;filename=" + fileName+".xlsx");
			response.setHeader( "Content-Disposition", "attachment;filename=\"" + name + "\".xlsx;filename*=utf-8''" + name +".xlsx");

			OutputStream os = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/vnd.ms-excel");
			response.setCharacterEncoding("utf-8");
			//将excel写入到输出流中
			workbook.write(os);
			os.flush();
			os.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * 居中
	 * @param workbook
	 * @return
	 */
	public static HSSFCellStyle getStyleByCENTER(HSSFWorkbook workbook,int size){
		//设置标题样式
		HSSFCellStyle style = workbook.createCellStyle();
		HSSFFont font = workbook.createFont();
		font.setBold(true);
		font.setFontName("宋体");
		font.setFontHeightInPoints((short) size);
		style.setFont(font);
		//水平居中
		style.setAlignment(HorizontalAlignment.CENTER);
		//垂直居中
		style.setVerticalAlignment(VerticalAlignment.CENTER);
		style.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));
		return style;
	}

	/**
	 * 带边框的样式
	 * @param workbook workbook
	 * @param size 字体大小
	 * @param isText 是否正文
	 * @return
	 */
	public static HSSFCellStyle getStyleByBorder(HSSFWorkbook workbook,int size,boolean isText){
		//设置标题样式
		HSSFCellStyle style = workbook.createCellStyle();
		HSSFFont font = workbook.createFont();
		if(!isText){
			font.setBold(true);
		}
		font.setFontName("宋体");
		font.setFontHeightInPoints((short) size);
		style.setFont(font);
		//水平居中
		style.setAlignment(HorizontalAlignment.CENTER);
		//垂直居中
		style.setVerticalAlignment(VerticalAlignment.CENTER);
		style.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));
		//边框
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		style.setBorderTop(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		return style;
	}


	public static HSSFCellStyle getDataStyle(HSSFWorkbook workbook,int size,boolean isSetBold,HSSFColor.HSSFColorPredefined background){
		//设置标题样式
		HSSFCellStyle style = workbook.createCellStyle();
		HSSFFont font = workbook.createFont();
		font.setBold(isSetBold);
		font.setFontName("宋体");
		font.setFontHeightInPoints((short) size);
		style.setFont(font);
		if(ObjectUtils.isNotEmpty(background)){//设置填充方式
			style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
			style.setFillForegroundColor(background.getIndex());
		}
		return style;
	}

	/**
	 * 解析上传的excel, 默认只解析第一张Sheet
	 *
	 * @param file     excel
	 * @param startRow 数据开始行
	 * @return List<String [ ]>
	 * @throws IOException
	 */
	public static List<String> getExcelData(MultipartFile file, int startRow, Integer endRow){
		int resultSize = 0;
		ArrayList<String> resultData = new ArrayList<>(resultSize);
		try {
			if (!checkFile(file)) {
				log.error("上传的excel文件格式有问题");
				return resultData;
			}

			//获得Workbook工作薄对象
			Workbook workbook = getWorkBook(file);
			if (ObjectUtils.isNotEmpty(workbook)) {
				//获取第一张sheet工作表
				Sheet sheet = workbook.getSheetAt(0);
				if (ObjectUtils.isEmpty(sheet)) {
					return resultData;
				}

				// 重新初始化List结果大小
				resultSize = sheet.getLastRowNum() + 1;
				//获得当前sheet的开始行
				int firstRowNum = sheet.getFirstRowNum();
				//获得当前sheet的结束行
				int lastRowNum = sheet.getLastRowNum();
				if(ObjectUtils.isNotEmpty(endRow)){
					lastRowNum = endRow;
				}

				//循环除了startRow的所有行,如果要循环除第一行以外的就firstRowNum+1
				for (int rowNum = firstRowNum + startRow; rowNum <= lastRowNum; rowNum++) {
					//获得当前行
					Row row = sheet.getRow(rowNum);
					if (rowIsEmpty(row)) {
						break;
					}
					//获得当前行的开始列
					int firstCellNum = row.getFirstCellNum();
					//获得当前行的列数
					int lastCellNum = row.getLastCellNum();
					//String[] cells = new String[lastCellNum];
					StringBuilder stringBuffer = new StringBuilder();
					//循环当前行
					for (int cellNum = firstCellNum; cellNum < lastCellNum; cellNum++) {
						Cell cell = row.getCell(cellNum);
						//cells[cellNum] = getCellValue(cell);
						String cellValue = getCellValue(cell);
						stringBuffer.append(getCellValue(cell)).append(",&");//加个&防止有答案中有,的
					}
					//resultData.add(cells);
					resultData.add(stringBuffer.toString());
				}
				workbook.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return resultData;
	}


	/**
	 * 检查文件格式
	 *
	 * @param file
	 * @throws IOException
	 */
	public static boolean checkFile(MultipartFile file) throws IOException {
		if (null == file) {
			log.error("文件不存在!");
			return false;
		}
		//获得文件名
		String fileName = file.getOriginalFilename();
		//判断文件是否是excel文件
		if (ObjectUtils.isEmpty(fileName) || (!fileName.endsWith("xls") && !fileName.endsWith("xlsx"))) {
			log.error(fileName + "不是excel文件");
			return false;
		}
		return true;
	}

	/**
	 * 获取工作簿对象
	 *
	 * @param file
	 * @return
	 */
	public static Workbook getWorkBook(MultipartFile file) {
		//获得文件名
		String fileName = file.getOriginalFilename();
		//创建Workbook工作薄对象,表示整个excel
		Workbook workbook = null;
		try {
			//获取excel文件的io流
			InputStream is = file.getInputStream();
			//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
			if(ObjectUtils.isNotEmpty(fileName)){
				if (fileName.endsWith("xls")) {
					//2003
					workbook = new HSSFWorkbook(is);
				} else if (fileName.endsWith("xlsx")) {
					//2007 及2007以上
					workbook = new XSSFWorkbook(is);
				}
			}
		} catch (IOException e) {
			log.error(e.getMessage());
		}
		return workbook;
	}

	public static String getCellValue(Cell cell) {
		String cellValue = "";
		if (cell == null) {
			return cellValue;
		}
		switch (cell.getCellTypeEnum()) {
			case NUMERIC:
				//数字
				cellValue = stringDateProcess(cell);
				break;
			case STRING:
				//字符串
				cellValue = String.valueOf(cell.getStringCellValue());
				break;
			case BOOLEAN:
				//Boolean
				cellValue = String.valueOf(cell.getBooleanCellValue());
				break;
			case FORMULA:
				//公式
				cellValue = String.valueOf(cell.getCellFormula());
				break;
			case BLANK:
				//空值
				cellValue = "";
				break;
			case ERROR:
				//故障
				cellValue = "非法字符";
				break;
			default:
				cellValue = "未知类型";
				break;
		}
		return cellValue;
	}


	public static String stringDateProcess(Cell cell) {
		String result = new String();
		if (HSSFDateUtil.isCellDateFormatted(cell)) {
			// 处理日期格式、时间格式
			SimpleDateFormat sdf = null;
			if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm")) {
				sdf = new SimpleDateFormat("HH:mm");
			} else {// 日期
				sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
			}
			Date date = cell.getDateCellValue();
			result = sdf.format(date);
		} else if (cell.getCellStyle().getDataFormat() == 58) {
			// 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58)
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
			double value = cell.getNumericCellValue();
			Date date = org.apache.poi.ss.usermodel.DateUtil
				.getJavaDate(value);
			result = sdf.format(date);
		} else {
			double value = cell.getNumericCellValue();
			CellStyle style = cell.getCellStyle();
			DecimalFormat format = new DecimalFormat();
			String temp = style.getDataFormatString();
			// 单元格设置成常规
			if ("General".equals(temp)) {
				int decimalPlaces = countDecimalPlaces(value);
				StringBuilder pattern = new StringBuilder("#.");
				for (int i = 0; i < decimalPlaces; i++) {
					pattern.append("#");
				}
				format.applyPattern(pattern.toString());
			}
			result = format.format(value);
		}

		return result;
	}

	public static int countDecimalPlaces(double value) {
		String stringValue = Double.toString(value);
		int integerPlaces = stringValue.indexOf('.');
		return stringValue.length() - integerPlaces - 1;
	}

	/**
	 * @return * @param null
	 * @Author
	 * @Description //TODO 判断excel的row是否全为空
	 * @Date 2019/12/2 19:30
	 * @Param
	 */
	public static boolean rowIsEmpty(Row row) {
		if (null == row) {
			return true;
		}
		for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
			Cell cell = row.getCell(c);
			if (cell != null && cell.getCellTypeEnum() != CellType.BLANK) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 模板下载
	 * @param response
	 * @param request
	 * @param filename
	 * @param path
	 * @throws IOException
	 */
	public void downloadTemplate(HttpServletResponse response, HttpServletRequest request, String filename, String path) throws IOException {

		InputStream inputStream = null;
		ServletOutputStream servletOutputStream = null;
		try {
			org.springframework.core.io.Resource resource = resourceLoader.getResource("classpath:" + path);

			response.setContentType("application/vnd.ms-excel");
			response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
			response.addHeader("charset", "utf-8");
			response.addHeader("Pragma", "no-cache");
			String encodeName = URLEncoder.encode(filename, StandardCharsets.UTF_8.toString());
			response.setHeader("Content-Disposition", "attachment; filename=\"" + encodeName + "\"; filename*=utf-8''" + encodeName);

			inputStream = resource.getInputStream();
			servletOutputStream = response.getOutputStream();
			IOUtils.copy(inputStream, servletOutputStream);
			response.flushBuffer();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (servletOutputStream != null) {
					servletOutputStream.close();
				}
				if (inputStream != null) {
					inputStream.close();
				}
				// jvm的垃圾回收
				System.gc();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

控制层接口

package com.yutu.garden.controller;

import com.yutu.garden.utils.ExcelUtilsWP;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@RestController
@RequestMapping("excel")
@Api(tags = "Excel模板下载")
public class ExcelTemplateController {

	@Resource
	private ExcelUtilsWP excelUtils;

	@ApiOperation("下载苗木计划清单模板")
	@GetMapping("/downloadPunishTemplate")
	public void downloadPunishTemplate(HttpServletResponse response, HttpServletRequest request) throws IOException {
		String filename = "苗木计划清单模板.xlsx";
		String path = "template/苗木计划清单模板.xlsx";
		excelUtils.downloadTemplate(response,request,filename,path);
	}
}

Excel模板存放位置

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1566765.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

音频转换工具 Bigasoft FLAC Converter for Mac

Bigasoft FLAC Converter for Mac是一款专为Mac用户设计的音频转换工具&#xff0c;它能够将FLAC音频文件高效、高质量地转换为其他常见的音频格式&#xff0c;如MP3、AAC等。这款软件具有直观易用的界面&#xff0c;使用户能够轻松上手&#xff0c;无需复杂的操作步骤即可完成…

AWS上面部署一台jenkins

问题 客户预算有限&#xff0c;需要在aws云上面搞一台EC2手动安装jenkins发版。 步骤 创建密钥对 在EC2服务里面创建密钥对&#xff0c;具体如下图&#xff1a; 设置密钥对&#xff0c;如下图&#xff1a; 保存好这个私钥文件&#xff0c;以便后续用这个私钥文件ssh登录j…

使用 Flume 将 CSV 数据导入 Kafka:实现实时数据流

使用 Flume 将 CSV 数据导入 Kafka&#xff1a;实现实时数据流 文介绍了如何使用 Apache Flume 将 CSV 格式的数据从本地文件系统导入到 Apache Kafka 中&#xff0c;以实现实时数据流处理。通过 Flume 的配置和操作步骤&#xff0c;我们可以轻松地将数据从 CSV 文件中读取并发…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之一 简单视频放大抖动效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之一 简单视频放大抖动效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之一 简单视频放大抖动效果 一、简单介绍 二、简单视频放大抖动效果实现原理 三、简单视频放大…

asf是什么格式的文件?用手机怎么打开?

由于手机操作系统和硬件的限制&#xff0c;大部分手机并不直接支持asf文件的播放。因此&#xff0c;如果你想在手机上打开asf文件&#xff0c;你可能需要先将文件转换为手机支持的格式&#xff0c;如MP4。可以通过使用一些视频转换软件来实现&#xff0c;比如野葱视频转换器。 …

原创【matcap材质在ue4中的实现办法】

matcap材质在ue4中的实现办法 2023-08-29 15:34 https://www.bilibili.com/video/BV1GR4y1b76n/?spm_id_from333.337.search-card.all.click&vd_sourced76b773892c830a157c0ccc97ba78411 评论(0)

2024阿里云老用户服务器优惠价格99元和199元

阿里云服务器租用价格表2024年最新&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核…

二期 1.1 微服务是什么?微服务与分布式架构的区别是什么?SpringBoot与Spring Cloud的区别是什么?

文章目录 前言一、单体架构二、微服务是什么?三、微服务与分布式的区别四、SpringBoot与Spring Cloud的区别?前言 欢迎大家来到二期Spring Cloud 微服务项目实战,首先我们应了解 单体架构是什么?它有哪些问题? 微服务是什么,与分布式架构的区别,Java中微服务框架Spring…

鸿蒙OS开发实例:【应用事件打点】

简介 传统的日志系统里汇聚了整个设备上所有程序运行的过程流水日志&#xff0c;难以识别其中的关键信息。因此&#xff0c;应用开发者需要一种数据打点机制&#xff0c;用来评估如访问数、日活、用户操作习惯以及影响用户使用的关键因素等关键信息。 HiAppEvent是在系统层面…

WPS二次开发系列:以自动播放模式打开PPT文档

在前面文章中 WPS SDK打开文档并实现保存回传 介绍了如何使用WPS SDK打开文档&#xff0c;那么我们是否能够实现在打开WPS 文档的时候能够传递一些参数来控制打开文档的行为呢&#xff0c;经过研究WPS SDK相关文档和API&#xff0c;最终实现了 以自动播放方式打开PPT文档功能。…

[lesson04]布尔类型和引用

布尔类型和引用 布尔类型 C中的布尔类型 C在C语言的基本类型系统上增加了boolC中的bool可取的值只有true和false理论上bool只占用一个字节 注意&#xff1a; true代表真值&#xff0c;编译器内部用1来表示 false代表非真值&#xff0c;编译器内部用0来表示 bool类型只有true(…

开源模型应用落地-chatglm3-6b模型小试-入门篇(一)

一、前言 刚开始接触AI时&#xff0c;您可能会感到困惑&#xff0c;因为面对众多开源模型的选择&#xff0c;不知道应该选择哪个模型&#xff0c;也不知道如何调用最基本的模型。但是不用担心&#xff0c;我将陪伴您一起逐步入门&#xff0c;解决这些问题。 在信息时代&#xf…

React + 项目(从基础到实战) -- 第三期

react内置hooks useState 如何让页面动起来(实时更新) import React,{FC,useState} from "react";const Demo:FC()>{let count0; //普通js变量无法触发组件更新function add(){count;console.log("count: ",count);}return <div><button onCl…

Transformer模型-用jupyter演示逐步计算attention

学习transformer模型-用jupyter演示如何计算attention&#xff0c;不含multi-head attention&#xff0c;但包括权重矩阵W。 input embedding&#xff1a;文本嵌入 每个字符用长度为5的向量表示&#xff1a; 注意力公式&#xff1a; 1&#xff0c;准备Q K V&#xff1a; 先 生…

云计算的安全需求

目录 一、概述 二、云安全服务基本能力要求 三、信息安全服务&#xff08;云计算安全类&#xff09;资质要求 3.1 概述 3.2 资质要求内容 3.2.1 组织与管理要求 3.2.2 技术能力要求 四、云安全主要合规要求 4.1 安全管理机构部门的建立 4.2 安全管理规范计划的编制 4…

AR/VR技术对制造业劳动力危机的影响

借助 AR/VR 的力量缩小现代制造业的技能差距 数字化转型仍然是企业的首要任务&#xff0c;其许多方面都需要人工干预。然而&#xff0c;推动此类举措所需的技术工人日益短缺。这就造成了我们所说的“制造业劳动力危机”。 制造业应当如何&#xff1a; 制造业用工危机正在影响…

IDEA 中能提高开发效率的插件

目录 前言 插件 Rainbow Brackets AceJump POJO to JSON Json Helper MybatisX Maven Helper PlantUML Integration TONYYI Lingma 前言 IDEA 里又很多好用的插件可以帮助我们提升开发效率&#xff0c;这里罗列下自己开发过程中常用的插件&#xff0c;善于利用插件&…

MySQL-视图:视图概述、创建、查看、更新、修改、删除

第14章 视图 1. 常见的数据库对象2. 视图概述2.1 为什么使用视图&#xff1f;2.2 视图的理解 3. 创建视图3.1 创建单表视图3.2 创建多表联合视图3.3 基于视图创建视图 4. 查看视图5. 更新视图的数据5.1 一般情况5.2 不可更新的视图 6. 修改、删除视图6.1 修改视图6.2 删除视图 …

Prisma ORM 5.12 发布,支持 Cloudflare D1 数据库

昨晚&#xff0c;Prisma ORM 发布了 5.12.0 稳定版本&#xff0c;在此版本中 Prisma ORM 新增了对 Cloudflare D1 的预览支持&#xff0c;现在我们可以选择将本地的 SQLite 数据库逐步迁移到 Cloudflare 上面&#xff0c;从而实现无需额外成本即可构建处理大量用户的应用程序。…

[计算机效率] 格式转换工具:格式工厂

3.14 格式转换工具&#xff1a;格式工厂 格式工厂是一款功能强大的多媒体格式转换软件&#xff0c;可以实现音频、视频、图片等多种格式的转换。它支持几乎所有类型的多媒体格式&#xff0c;包括视频、音频、图片、字幕等&#xff0c;可以轻松实现格式之间的转换&#xff0c;并…