实际开发中,常见pdf|word|excel等文件的预览和下载

实际开发中,常见pdf|word|excel等文件的预览和下载

    • 背景
    • 相关类型数据之间的转换
      • 1、File转Blob
      • 2、File转ArrayBuffer
      • 3、Blob转ArrayBuffer
      • 4、Blob转File
      • 5、ArrayBuffer转Blob
      • 6、ArrayBuffer转File
    • 根据Blob/File类型生成可预览的Base64地址
    • 基于Blob类型的各种文件的下载
    • 各种类型文件的预览及其效果
      • 1、当前使用的node版本
      • 2、 业务场景
      • 3、图片类型预览
        • 3.1、安装依赖
        • 3.2、ImagePreview.vue
        • 3.3、效果
      • 4、Excel文件的预览
        • 4.1、依赖安装
        • 4.2、ExcelPreview.vue
        • 4.3、预览效果
      • 5、word文件的预览
        • 5.1、依赖安装
        • 5.2、WordPreview.vue
        • 5.3、预览效果
      • 6、pdf文件的预览
        • 6.1、依赖安装
        • 6.2、PdfPreview.vue
        • 6.3、预览效果
      • 7、json/xml文件的预览
        • 7.1、依赖安装
        • 7.2、全局引入
        • 7.3、JsonViewer组件的使用
        • 7.4、预览效果
      • 8、bim文件的预览
        • 8.1、依赖安装
        • 8.2、GeoBimPreview.vue
        • 8.3、预览效果

背景

实际开发中,大部分文件的预览会以流的方式传输,前端通过Element等UI库提供的上传组件传给后端File类型数据, 后端返回给前端Blob/ArrayBuffer类型数据 , 前端最终借助各种第三方工具或者自定义tool方法, 实现各种类型文件的下载或者预览. 少部分的会以文件地址的方式进行传输, 那么我们直接访问那个文件url即可.

相关类型数据之间的转换

1、File转Blob

export function fileToBlob(file: File) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      const arrayBuffer: any = reader.result;
      const blob = new Blob([arrayBuffer], { type: file.type });
      resolve(blob);
    };
    reader.onerror = reject;
    reader.readAsArrayBuffer(file);
  });
}

在这里插入图片描述

2、File转ArrayBuffer

export function fileToArrayBuffer(file: File) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      const arrayBuffer: any = reader.result;
      resolve(arrayBuffer);
    };
    reader.onerror = reject;
    reader.readAsArrayBuffer(file);
  });
}

3、Blob转ArrayBuffer

export function blobToArrayBuffer(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsArrayBuffer(blob);
  });
}

4、Blob转File

export function blobToFile(blob, fileName, fileType) {
  return new File([blob], fileName, { type: fileType })
}

5、ArrayBuffer转Blob

export function arrayBufferToBlob(arrayBuffer, blobType = 'application/octet-stream') {
	const blob = new Blob([arrayBuffer], { type: blobType  });
  	return blob;
}

6、ArrayBuffer转File

export function arrayBufferToFile(arrayBuffer, fileName, fileType = 'text/plain') {
	const file= new File([arrayBuffer], fileName, { type: fileType  });
  	return file;
}

根据Blob/File类型生成可预览的Base64地址

有些第三方预览工具不识别Blob/File, 如viewerjsv-viewer 预览图片的时候,是需要图片对应的src的,而不是Blob/File

export function createUrlByBlobOrFile(data: any) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      resolve(reader.result);
    };
    reader.onerror = reject;
    reader.readAsDataURL(data);
  });
}

基于Blob类型的各种文件的下载

下载的文件响应类型可打印FIle/Blob对象查看,可执行:downloadFileUtil(fileBlob, fileBlob.type, fileBlob.fileName)

export function downloadFileUtil(data: Blob, responseType: string, fileName: any = new Date().valueOf()) {
	  const blob = new Blob([data], { type: responseType });
	  // 创建一个<a></a>标签
	  let a: HTMLAnchorElement | null = document.createElement('a');
	  const blobUrl = window.URL.createObjectURL(blob);
	  a.href = blobUrl;
	  a.download = fileName;
	  a.style.display = 'none';
	  document.body.appendChild(a);
	  a.click();
	  a.remove();
	  // 释放createObjectURL创建的资源
	  window.URL.revokeObjectURL(blobUrl);
}

各种类型文件的预览及其效果

个别预览的第三方插件库,需要使用特定的某些版本,当前指定的版本库都是可用的。

1、当前使用的node版本

在这里插入图片描述

2、 业务场景

  • 用户通过上传组件上传附件

用户从本地上传的附件拿到的类型是File, 保存之后, 拿到的就是文件列表项对应的Blob类型。
在这里插入图片描述

3、图片类型预览

图片类型预览使用的是v-viewerviewerjs, 可支持的预览图片类型有:jpg, jpeg, png, gif

3.1、安装依赖
yarn add v-viewer@^3.0.21 viewerjs@^1.11.7
3.2、ImagePreview.vue

v-viewerviewerjs 可以通过指令、组件和api三种方式实现预览。 实际开发中,基本上都是使用的是Blob类型,Blob类型转换为Base64地址后, 是不能通过import { api as viewerApi } from 'v-viewer';的方式预览的,尽管api的方式很简单,但它貌似只是支持本地文件URL/服务器文件URL。

通过使用viewer组件,借助img标签可以识别Base64图片路径,从而通过点击img列表,实现图片预览

<template>
  <div class="image-preview">
    <viewer :images="props.images" class="v-viewer">
      <img
        v-for="(imgItem, index) in props.images"
        :key="index"
        class="view-img-item"
        :src="imgItem.url"
        :alt="imgItem.name"
        :title="imgItem.name"
      />
    </viewer>
    <div class="auto-close-preview-com">
      <Close class="close-icon" @click="closeImgPreviewFn" />
    </div>
  </div>
</template>

<script lang="ts" setup>
import 'viewerjs/dist/viewer.css';
import { component as Viewer } from 'v-viewer';
import { onMounted } from 'vue';
import { ElMessage } from 'element-plus';


const props = defineProps({
  images: {
    type: Array as any,  // images存储的是Blob转成Base64的数组,类型转换上文createUrlByBlobOrFile可实现
    default: () => [],
  },
});
const emits = defineEmits(['closeImgPreview']);

function closeImgPreviewFn() {
  emits('closeImgPreview');
}
onMounted(() => {
  ElMessage.info('点击图片列表可预览~');
});
</script>

<style lang="css" scoped>
.image-preview {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 9998;
  background-color: rgb(0 0 0 / 70%);
  .v-viewer {
    width: 100%;
    height: 100%;
    .view-img-item {
      width: 250px;
      height: 250px;
      margin-right: 20px;
    }
  }
  .auto-close-preview-com {
    position: absolute;
    -webkit-app-region: no-drag;
    background-color: rgb(0 0 0 / 50%);
    border-radius: 50%;
    cursor: pointer;
    height: 80px;
    overflow: hidden;
    right: -40px;
    top: -40px;
    transition: background-color 0.15s;
    width: 80px;
    color: #ffffff;
    .close-icon {
      bottom: 15px;
      left: 15px;
      position: absolute;
      background-position: -260px 0;
      font-size: 0;
      height: 20px;
      line-height: 0;
      width: 20px;
    }
  }
}
</style>
3.3、效果

在这里插入图片描述

4、Excel文件的预览

Excel文件预览使用的是xlsx 插件库, 可支持类型有:xls, xlsx

4.1、依赖安装
yarn add xlsx@^0.18.5
4.2、ExcelPreview.vue
<template>
  <div class="xlsx-preview-box"></div>
</template>

<script lang="ts" setup>
import { onMounted } from 'vue';
// XLSX: 无法预览docx文件, 预览pdf也会乱码  只能预览xlsx文件
import * as XLSX from 'xlsx';

const props = defineProps({
  fileBlob: {
    type: Blob,
    default: () => null,
  },
});

onMounted(() => {
  if (props.fileBlob) {
    const reader = new FileReader();
    // 通过readAsArrayBuffer将blob转换为ArrayBuffer
    reader.readAsArrayBuffer(props.fileBlob);
    reader.onload = (event: any) => {
      // 读取ArrayBuffer数据变成Uint8Array
      const data = new Uint8Array(event.target.result);
      // 这里的data里面的类型和后面的type类型要对应
      const workbook = XLSX.read(data, { type: 'array' });
      const sheetNames = workbook.SheetNames; // 工作表名称
      const worksheet = workbook.Sheets[sheetNames[0]];
      const html = XLSX.utils.sheet_to_html(worksheet);
      document.getElementsByClassName('xlsx-preview-box')[0].innerHTML = html;
    };
  }
});
</script>

<style lang="css">
.xlsx-preview-box {
  width: 100%;
  height: 100%;
  overflow: auto;
  table {
    width: 100%;
    border-spacing: 0;
    tr {
      height: 40px;
      font-size: 14px;
      color: #666666;
      line-height: 14px;
      font-weight: 400;
    }
    tr:first-child {
      background-color: #ececec !important;
      height: 60px;
      font-size: 16px;
      color: #666666;
      font-weight: 700;
    }
    td {
      min-width: 80px;
      text-align: center;
      border: 1px solid #cccccc;
    }
    tr:nth-child(2n) {
      background-color: #fafafa;
    }

    tr:nth-child(2n + 1) {
      background-color: #ffffff;
    }
  }
}
</style>
4.3、预览效果

在这里插入图片描述

5、word文件的预览

word文件预览使用的是docx-preview 插件库, 可支持类型有:doc, docx

5.1、依赖安装
yarn add docx-preview@0.3.0

docx-preview 需要是0.3.0版本,最新的0.3.3版本会报docx-preview类型错误。且最新的版本解析的blob文件类型和0.3.0版本不一致,最新版本还会预览失败:报(Can’t find end of central directory : is this a zip file ? If it is, see)。

5.2、WordPreview.vue
<template>
  <div ref="wordPreviewRef" class="word-preview"></div>
</template>

<script lang="ts" setup>
import { ref, nextTick } from 'vue';
// docx-preview 需要是0.3.0版本,最新的0.3.3版本会报docx-preview类型错误
// 且最新的版本解析的blob类型和0.3.0版本不一致
// 最新版本还会预览失败:报(Can't find end of central directory : is this a zip file ? If it is, see)
import { renderAsync } from 'docx-preview';

const props = defineProps<{
  wordBlob: any;
}>();

const wordPreviewRef = ref({});

nextTick(() => {
  renderAsync(
    props.wordBlob, // blob 的type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
    wordPreviewRef.value as HTMLElement, // HTMLElement 渲染文档内容的元素,
  );
});
</script>

<style lang="scss" scoped>
.word-preview {
  width: 100%;
  height: 100%;
  overflow: auto;
}
</style>
5.3、预览效果

在这里插入图片描述

6、pdf文件的预览

pdf文件预览使用的是pdfjs-dist 插件库, 可支持类型有:pdf

6.1、依赖安装
yarn add pdfjs-dist@2.16.105

pdfjs-dist 底层是pdfjs。不建议使用打包后的mjs类型的版本包。因为不支持线上环境对GlobalWorkerOptions.workerSrc的支持。具体的是:本地可以引入node_module路径,但是正式环境没这个路径;如果把对应的pdf.worker.min.mjs放到assets下,会报错:Failed to resolve module specifier '@/assets/pdfjs/pdf.worker.min.mjs; 如果放到public下,会报错Failed to load module script, public目录文件不会被编译,浏览器无法识别mjs文件

6.2、PdfPreview.vue
<template>
  <div class="pdf-preview">
    <!-- block: 避免一个视图显示多个canvas页 -->
    <canvas
      v-for="pageIndex in pdfPages"
      :id="`pdf-canvas-` + pageIndex"
      ref="pdfPreviewRef"
      :key="pageIndex"
      style="display: block"
    ></canvas>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, nextTick, reactive } from 'vue';

// import 'pdfjs-dist/web/pdf_viewer.css';
// 4.5.136版本
// import * as pdfjsLib from 'pdfjs-dist'; // /legacy/build/pdf.js
// import * as pdfjsViewer from 'pdfjs-dist/web/pdf_viewer.js';
import 'pdfjs-dist/web/pdf_viewer.css';
import * as pdfjsLib from 'pdfjs-dist';
import { blobToArrayBuffer } from '@/utils/tools';

const props = defineProps<{
  pdfBlob: any;
}>();

const pdfPreviewRef = ref({});
// pdf页数
const pdfPages = ref(0);
// pdf缩放比例
const pdfScale = ref(2.5); // 可以控制canvas的宽高
// pdf文档流,
// 这个不能使用ref,使用ref会报错: Cannot read from private field
let pdfDoc = reactive<any>({});

const renderPdf = (num) => {
  pdfDoc.getPage(num).then((page) => {
    const canvasId = `pdf-canvas-${num}`;
    const canvas: any = document.getElementById(canvasId);
    const ctx = canvas?.getContext('2d');
    const dpr = window.devicePixelRatio || 1;
    const bsr =
      ctx.webkitBackingStorePixelRatio ||
      ctx.mozBackingStorePixelRatio ||
      ctx.msBackingStorePixelRatio ||
      ctx.oBackingStorePixelRatio ||
      ctx.backingStorePixelRatio ||
      1;
    const ratio = dpr / bsr;
    const viewport = page.getViewport({ scale: pdfScale.value });
    canvas.width = viewport.width * ratio;
    canvas.height = viewport.height * ratio;
    canvas.style.width = `${viewport.width}px`;
    canvas.style.height = `${viewport.height}px`;
    ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
    const renderContext = {
      canvasContext: ctx,
      viewport: viewport,
    };
    page.render(renderContext);
    if (num < pdfPages.value) {
      renderPdf(num + 1);
    }
  });
};

// 获取pdf文档流与pdf文件的页数
const loadFile = async () => {
  //  string | URL | TypedArray | ArrayBuffer | DocumentInitParameters
  const pdfArrayBuffer: any = await blobToArrayBuffer(props.pdfBlob);
  const loadingTask = pdfjsLib.getDocument(pdfArrayBuffer);
  loadingTask.promise.then((pdf) => {
    pdfDoc = pdf; // 获取pdf文档流
    pdfPages.value = pdf.numPages; // 获取pdf文件的页数
    nextTick(() => {
      renderPdf(1);
    });
  });
};

onMounted(async () => {
  // 正式环境找不到node_modules
  // pdfjsLib.GlobalWorkerOptions.workerSrc =
  //   '../../../node_modules/pdfjs-dist/build/pdf.worker.min.mjs';
  // 放在assets下: Failed to resolve module specifier '@/assets/pdfjs/pdf.worker.min.mjs
  // pdfjsLib.GlobalWorkerOptions.workerSrc = '@/assets/pdfjs/pdf.worker.min.mjs';
  // const baseurl = window.location.origin + window.location.pathname; // 本地路径
  // ${baseurl}pdfjs/pdf.worker.min.mjs 静态服务访问的返回的是流
  // pdfjsLib.GlobalWorkerOptions.workerSrc = `${baseurl}pdfjs/pdf.worker.min.mjs`; // Failed to load module script
  // public/pdfjs/pdf.worker.js: 将'../../../node_modules/pdfjs-dist/build/pdf.worker.js';复制到public目录下
  pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js';  // “pdfjs/”不能写成“/pdfjs/”, 前者是相对路径, 后者是绝对路径(相对线上环境服务器)
  loadFile();
});
</script>
<style lang="scss" scoped>
.pdf-preview {
  width: 100%;
  height: 100%;
  overflow: auto;
}
</style>

6.3、预览效果

在这里插入图片描述

7、json/xml文件的预览

vue-json-viewer支持jsonxml文件的预览

7.1、依赖安装
yarn add vue-json-viewer@^3.0.4
7.2、全局引入

在这里插入图片描述

7.3、JsonViewer组件的使用

fileData存储的是后端接口返回的json字符串

<json-viewer v-else-if="preState.fileType === 'Json'" :value="preState.fileData" />
7.4、预览效果

在这里插入图片描述
在这里插入图片描述

8、bim文件的预览

geobim文件的预览使用的是@xbim/viewer插件库,当前使用的方式支持BlobUrl两种方式

8.1、依赖安装
yarn add @xbim/viewer@^2.1.0-pre202305041434
8.2、GeoBimPreview.vue

该组件接收的是url, 但是loadGeoBim处理兼容了Blob

<template>
  <canvas id="bim-canvas" style="width: 100%; height: 100%"></canvas>
</template>

<script lang="ts" setup>
import { watch, nextTick } from 'vue';
import { Grid, NavigationCube, Viewer, ViewType } from '@xbim/viewer';

const props = defineProps({
  dwgUrl: {
    type: String,
    default: () => '',
  },
});
let viewer;
const setViewerOptions = () => {
  viewer.background = [26, 51, 76, 255];
  viewer.highlightingColour = [0, 0, 225, 200];
  viewer.brightness = -0.5;
  viewer.hoverPickColour = [0, 0, 225, 200];
};
const setViewerPlugin = () => {
  const cube = new NavigationCube();
  cube.ratio = 0.05;
  // eslint-disable-next-line no-multi-assign
  cube.passiveAlpha = cube.activeAlpha = 0.85;
  viewer.addPlugin(new Grid());
  viewer.addPlugin(cube);
};
const token = localStorage.getItem('TOKEN') as string;
const headers = {
  Authorization: `Bearer ${JSON.parse(token).access_token}`,
};
const loadGeoBim = (dwgUrl) => {
  const check = Viewer.check();
  if (check.noErrors) {
    nextTick(() => {
      viewer = new Viewer('bim-canvas');
      setViewerOptions();
      setViewerPlugin();
      viewer.on('loaded', function () {
        viewer.show(ViewType.DEFAULT, undefined, undefined, false);
        viewer.start();
      });
      // 前置管理、任务管理、数据管理里访问的数据是四库的后端接口返回的文件流,服务管理里访问的是可视化系统后台接口返回的文件地址
      // node_modules\.vite\deps\@xbim_viewer.js  修复bim的左右键
      fetch(dwgUrl, { headers })
        .then((responce) => responce.arrayBuffer())
        .then((arrayBuffer) => {
          const blob = new Blob([arrayBuffer], { type: 'application/octet-stream' });
          viewer.load(blob);
        })
        .catch((err) => {
          viewer.load(dwgUrl);
        });
    });
  }
};
watch(
  () => props.dwgUrl,
  (dwgUrl) => {
    loadGeoBim(dwgUrl);
  },
  {
    immediate: true,
    deep: true,
  },
);
</script>

8.3、预览效果

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt使用CMake编译项目时报错:#undefined reference to `vtable for MainView‘

博主将.h文件和.cpp文件放到了不同的文件目录下面&#xff0c;如下图所示&#xff1a; 于是构建项目的时候就报错了#undefined reference to vtable for MainView&#xff0c;这个是由于src/view目录下的CMake无法自动moc头文件导致的&#xff0c;需要手动moc include/view目录…

会员制电商创新:开源 AI 智能名片与 2+1 链动模式的协同赋能

摘要&#xff1a;本文聚焦于电商领域会员制的关键作用&#xff0c;深入探讨在传统交易模式向数字化转型过程中&#xff0c;如何借助开源 AI 智能名片以及 21 链动模式商城小程序&#xff0c;实现对会员数据的精准挖掘与高效利用&#xff0c;进而提升企业的营销效能与客户洞察能…

第27周:文献阅读及机器学习

目录 摘要 Abstract 一、文献阅读 发现问题 研究方法 CNN-LSTM DT SVR 创新点 案例分析 数据准备 模型性能 预测模型的实现 仿真实验及分析 二、LSTM 1、基本结构 2、具体步骤 3、举例说明 4、原理理解 总结 摘要 本周阅读文献《Short-term water qua…

【机器遗忘之UNSIR算法】2023年IEEE Trans期刊论文:Fast yet effective machine unlearning

1 介绍 年份&#xff1a;2023 期刊&#xff1a;IEEE Transactions on Neural Networks and Learning Systems 引用量&#xff1a;170 Tarun A K, Chundawat V S, Mandal M, et al. Fast yet effective machine unlearning[J]. IEEE Transactions on Neural Networks and Le…

Linux-----进程处理(waitpid,进程树,孤儿进程)

目录 waitpid等待 进程树 孤儿进程 waitpid等待 Linux中父进程除了可以启动子进程&#xff0c;还要负责回收子进程的状态。如果子进程结束后父进程没有正常回收&#xff0c;那么子进程就会变成一个僵尸进程——即程序执行完成&#xff0c;但是进程没有完全结束&#xff0c;其…

Docker- Unable to find image “hello-world“locally

Docker- Unable to find image “hello-world“locally 文章目录 Docker- Unable to find image “hello-world“locally问题描述一. 切换镜像1. 编辑镜像源2. 切换镜像内容 二、 检查设置1、 重启dockers2、 检查配置是否生效3. Docker镜像源检查4. Dokcer执行测试 三、自定义…

Android配件应用默认启动与USB权限申请区别

使用效果&#xff1a; USB配件授权演示 选择USB配件默认打开应用 申请USB配件使用权限

vue2框架配置路由设计打印单

业务效果: 查询出列表后&#xff0c;点击申请单按钮&#xff0c;弹出申请表格&#xff0c;可进行打印 后端实现 控制器、服务层等省略&#xff0c;关联查出数据提供接口给前端即可 <!--获取详细信息(用于申请单打印)--><select id"selectXxxxDetail" par…

第29天:Web开发-PHP应用弱类型脆弱Hash加密Bool类型Array数组函数转换比较

#知识点 1、安全开发-原生PHP-弱类型脆弱 2、安全开发-原生PHP-函数&数据类型 3、安全开发-原生PHP-代码审计案例 一、PHP弱类型对比 1、 和 两个等号是弱比较&#xff0c;使用进行对比的时候&#xff0c;php解析器就会做隐式类型转换&#xff0c;如果两个值的类型不相等就…

在Ubuntu 18.04.6 LTS安装OpenFace流程

一、修改配置:将gcc8&#xff0c;g8作为默认选项 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 100 sudo update-alternatives --config gcc 选择版本&#xff0c;再查看gcc --version sudo update-alternatives --install /usr/bin/g g /usr/bin/g-…

【亚马逊云科技】基于Amazon EKS部署高可用的OceanBase的最佳实践

一、前言 随着企业业务的快速发展和数据量的不断增长&#xff0c;高性能、高可用的数据库解决方案成为了关键需求。OceanBase作为一款分布式关系型数据库&#xff0c;以其高扩展性、高可用性和高性能的特点&#xff0c;逐渐受到企业的广泛关注。然而&#xff0c;在复杂的分布式…

计算机网络:网络层知识点及习题(一)

网课资源&#xff1a; 湖科大教书匠 1、概述 网络层实现主机到主机的传输&#xff0c;主要有分组转发和路由选择两大功能 路由选择处理机得出路由表&#xff0c;路由表再生成转发表&#xff0c;从而实现分组从不同的端口转发 网络层向上层提供的两种服务&#xff1a;面向连接…

简历_熟悉缓存高并发场景处理方法,如缓存穿透、缓存击穿、缓存雪崩

系列博客目录 文章目录 系列博客目录1.缓存穿透总结 2.缓存雪崩3.缓存击穿代码总结 1.缓存穿透 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据库。 常见的解决方案有两种&#xff1a; 缓存空对…

阿里云 人工智能与机器学习

阿里云的 人工智能&#xff08;AI&#xff09;与机器学习&#xff08;ML&#xff09; 服务为企业提供了全面的AI解决方案&#xff0c;帮助用户在多个行业实现数据智能化&#xff0c;提升决策效率&#xff0c;推动业务创新。阿里云通过先进的技术和丰富的工具&#xff0c;支持用…

LabVIEW语言学习过程是什么?

学习LabVIEW语言的过程可以分为几个阶段&#xff0c;每个阶段的重点内容逐步加深&#xff0c;帮助你从入门到精通。以下是一个简洁的学习过程&#xff1a; ​ 1. 基础入门阶段 理解图形化编程&#xff1a;LabVIEW是一种图形化编程语言&#xff0c;与传统的文本编程语言不同&am…

【办公类-47-02】20250103 课题资料快速打印(单个docx转PDF,多个pdf合并一个PDF 打印)

背景需求&#xff1a; 2023区级大课题《运用Python优化3-6岁幼儿学习活动材料的实践研究》需要做阶段资料 本来应该2024年6月就提交电子稿和打印稿。可是python学具的教学实验实在太多了&#xff0c;不断生成&#xff0c;我忙着做教学&#xff0c;都没有精力去整理。 2025年…

【CSS】第一天 基础选择器与文字控制属性

【CSS】第一天 1. CSS定义2. css引入方式2.1 内部样式2.2 外部样式2.3 行内样式 3. 选择器3.1 标签选择器3.2 类选择器3.3 id选择器3.4 通配符选择器 1. CSS定义 层叠样式表(CSS)是一种样式表语言&#xff0c;用来描述HTML文档的呈现(美化内容)。 书写位置&#xff1a;title标…

Nginx (40分钟学会,快速入门)

目录​​​​​​​ 一、什么是Nginx ? 可以做什么 &#xff1f; 二、正向代理和反向代理 三、负载均衡 四、动静分离 五、Nginx 常用命令 六、Nginx实战及总结 一、什么是Nginx ? 可以做什么 &#xff1f; Nginx 是高性能的 HTTP 和反向代理的 web 服务器&#xff0c…

单片机从入门到放弃教程001

1. 单片机介绍 单片微型计算机(Single Chip Microcomputer)简称单片机&#xff0c;是典型的嵌入式微处理器(Micro Controller Unit简称MCU)&#xff0c;是一种将中央处理器&#xff08;CPU&#xff09;、内存、输入输出接口以及其他功能模块集成在单一芯片上的微型计算机。 1…

[极客大挑战 2019]HardSQL 1

看了大佬的wp&#xff0c;没用字典爆破&#xff0c;手动试出来的&#xff0c;屏蔽了常用的关键字&#xff0c;例如&#xff1a;order select union and 最搞的是&#xff0c;空格也有&#xff0c;这个空格后面让我看了好久&#xff0c;该在哪里加括号。 先传入1’ 1试试&#…