当前位置: 首页 > news >正文

SpringBoot实现的大文件上传

前言

大文件分片上传和断点续传是为了解决在网络传输过程中可能遇到的问题,以提高文件传输的效率和稳定性。

  • 首先,大文件分片上传是将大文件分割成较小的片段进行上传。这样做的好处是可以减少单个文件的传输时间,因为较小的文件片段更容易快速上传到目标服务器。同时,如果在传输过程中出现错误或中断,只需要重新上传出现问题的文件片段,而不需要重新上传整个文件,从而减少了传输的时间和带宽消耗。
  • 其次,断点续传是指在文件传输过程中,如果传输被中断或者发生错误,可以从上一次中断的地方继续传输,而不是从头开始。这对于大文件的传输尤为重要,因为传输一个大文件可能需要较长的时间,而中断可能是由网络问题、电源故障、软件崩溃或其他因素引起的。断点续传功能允许用户在中断后恢复传输,而无需重新开始,节省了时间和资源。

大文件分片上传和断点续传在以下情况下尤为重要:

  1. 低带宽网络环境:在网络速度较慢或不稳定的情况下,将大文件分割为较小的片段进行上传可以降低传输的时间和失败的风险。
  2. 大文件传输:对于大文件,一次性完整上传可能需要很长时间,而且中途出现问题时需要重新传输整个文件,因此将文件分割并实现断点续传功能可以提高效率和可靠性。
  3. 网络中断或传输错误:网络中断、电源故障或软件崩溃等因素可能导致文件传输中断,断点续传功能可以从中断处恢复,避免重新传输整个文件。
  4. 多用户并发上传:在有多个用户同时上传文件的情况下,分片上传和断点续传可以减少对服务器资源的占用,提高并发传输的效率。

前端

采用百度的webuploader,在file.html中引用webuploader.js、jquery.js

代码如下:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>大文件上传下载</title><link rel="stylesheet" type="text/css" href="webuploader.css"><script src="jquery.js"></script><script src="webuploader.js"></script><style>#upload-container {width: 100px;height: 50px;background: #94d3e7;padding-bottom: 10px;}</style>
</head>
<body><div id="upload-container"><span>文件拖拽上传</span></div><button id="picker" style="margin-top: 20px">分片上传</button><div id="upload-list"></div><hr/>
<a href="/file/download" >普通下载</a>
<hr/>
<a href="/file/downloads" target="_blank">分片下载</a></body>
<script>$('#upload-container').click(function (event) {$("#picker").find('input').click();});// 初始化上传组件const uploader = WebUploader.create({auto: true,swf: 'Uploader.swf', // swf文件路径server: '/file/upload', // 上传接口dnd: '#upload-container',pick: '#picker',  // 内部根据当前运行创建multiple: true,     // 选择多个chunked: true,      // 开启分片threads: 8,        // 并发数,默认 3chunkRetry: 8,         // 如果遇到网络错误,重新上传次数method: 'POST',fileSizeLimit: 1024 * 1024 * 1024 * 10, // 文件总大小为10GfileSingleSizeLimit: 1024 * 1024 * 1024 * 1,  // 单个文件大小最大为1GfileVal: 'upload'});// 入队之前触发事件uploader.on("beforeFileQueued", function (file) {// 获取文件后缀console.log(file.name);});// 当有文件被添加进队列的时候uploader.on('fileQueued', function (file) {$('#upload-list').append( '<div id="' + file.id + '" class="item">' +'<h4 class="info">' + file.name + '</h4>' +'<p class="state">等待上传...</p>' +'</div>' );});// 文件上传过程中创建进度条实时显示。uploader.on('uploadProgress', function (file, percentage) {var $li = $('#' + file.id),$percent = $li.find('.progress .progress-bar');// 避免重复创建if (!$percent.length) {$percent = $('<div class="progress progress-striped active">' +'<div class="progress-bar" role="progressbar" style="width: 0%">' +'</div>' +'</div>').appendTo($li).find('.progress-bar');}$li.find('p.state').text('上传中');$percent.css('width', percentage * 100 + '%');});uploader.on( 'uploadSuccess', function( file ) {$( '#'+file.id ).find('p.state').text('已上传');});uploader.on( 'uploadError', function( file ) {$( '#'+file.id ).find('p.state').text('上传出错');});uploader.on( 'uploadComplete', function( file ) {$( '#'+file.id ).find('.progress').fadeOut();});</script>
</html>

后端

1.Pom文件添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.4</version><relativePath/></parent><groupId>com.liyh</groupId><artifactId>springboot-file</artifactId><version>0.0.1</version><name>springboot-file</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency><!-- 做断点下载使用 --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
2.yml配置文件
# 配置服务端口
server:port: 8018spring:servlet:multipart:# Spring Boot中有默认的文件上传组件,在使用ServletFileUpload时需要关闭Spring Boot的默认配置enabled: false# 设置单个文件大小max-file-size: 1GB# 设置单次请求文件的总大小max-request-size: 10GB

3..编写测试接口controller

package com.liyh.controller;import com.liyh.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 文件上传测试接口** @author liyh*/
@RestController
@RequestMapping("/file")
public class FileController {@Autowiredprivate FileService fileService;/*** 单个文件上传,支持断点续传*/@PostMapping("/upload")public void upload(HttpServletRequest request, HttpServletResponse response) {try {fileService.upload(request, response);} catch (Exception e) {e.printStackTrace();}}/*** 普通文件下载*/@GetMapping("/download")public void download(HttpServletRequest request, HttpServletResponse response) throws IOException {fileService.download(request, response);}/*** 分片文件下载*/@GetMapping("/downloads")public String downloads() throws IOException {fileService.downloads();return "下载成功";}}

4.编写service 

package com.liyh.service;import com.liyh.entity.DownloadFileInfo;
import com.liyh.entity.FileInfo;
import com.liyh.entity.UploadFileInfo;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@Service
public class FileService {/*** 编码*/private static final String UTF_8 = "UTF-8";/*** 文件上传路径(当前项目路径下,也可配置固定路径)*/private String uploadPath = System.getProperty("user.dir") + "/springboot-file/upload/";/*** 下载指定文件*/private String downloadFile = "D:\\Download\\git.exe";/*** 文件下载地址(当前项目路径下,也可配置固定路径)*/private String downloadPath = System.getProperty("user.dir") + "/springboot-file/download/";/*** 分片下载每一片大小为50M*/private static final Long PER_SLICE = 1024 * 1024 * 50L;/*** 定义分片下载线程池*/private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());/*** final string*/private static final String RANGE = "Range";/*** 上传文件*/public void upload(HttpServletRequest request, HttpServletResponse response) throws Exception {// 获取ServletFileUploadServletFileUpload servletFileUpload = getServletFileUpload();List<FileItem> items = servletFileUpload.parseRequest(request);// 获取文件信息UploadFileInfo uploadFileInfo = getFileInfo(items);// 写入临时文件writeTempFile(items, uploadFileInfo);// 判断是否合并mergeFile(uploadFileInfo);// 返回结果response.setCharacterEncoding(UTF_8);response.getWriter().write("上传成功");}/*** 获取ServletFileUpload*/private ServletFileUpload getServletFileUpload() {// 设置缓冲区大小,先读到内存里在从内存写DiskFileItemFactory factory = new DiskFileItemFactory();factory.setSizeThreshold(1024);File file = new File(uploadPath);// 如果文件夹不存在则创建if (!file.exists() && !file.isDirectory()) {file.mkdirs();}factory.setRepository(file);// 解析ServletFileUpload upload = new ServletFileUpload(factory);// 设置单个大小与最大大小upload.setFileSizeMax(1 * 1024 * 1024 * 1024L);upload.setSizeMax(10 * 1024 * 1024 * 1024L);return upload;}/*** 获取文件信息** @param items* @return* @throws UnsupportedEncodingException*/private UploadFileInfo getFileInfo(List<FileItem> items) throws UnsupportedEncodingException {UploadFileInfo uploadFileInfo = new UploadFileInfo();for (FileItem item : items) {if (item.isFormField()) {// 获取分片数据if ("chunk".equals(item.getFieldName())) {uploadFileInfo.setCurrentChunk(Integer.parseInt(item.getString(UTF_8)));}if ("chunks".equals(item.getFieldName())) {uploadFileInfo.setChunks(Integer.parseInt(item.getString(UTF_8)));}if ("name".equals(item.getFieldName())) {uploadFileInfo.setFileName(item.getString(UTF_8));}}}return uploadFileInfo;}/*** 写入临时文件** @param items* @param uploadFileInfo* @throws Exception*/private void writeTempFile(List<FileItem> items, UploadFileInfo uploadFileInfo) throws Exception {// 获取文件基本信息后for (FileItem item : items) {if (!item.isFormField()) {// 有分片需要临时目录String tempFileName = uploadFileInfo.getFileName();if (StringUtils.isNotBlank(tempFileName)) {if (uploadFileInfo.getCurrentChunk() != null) {tempFileName = uploadFileInfo.getCurrentChunk() + "_" + uploadFileInfo.getFileName();}// 判断文件是否存在File tempFile = new File(uploadPath, tempFileName);// 断点续传,判断文件是否存在,若存在则不传if (!tempFile.exists()) {item.write(tempFile);}}}}}/*** 判断是否合并** @param uploadFileInfo* @throws IOException* @throws InterruptedException*/private void mergeFile(UploadFileInfo uploadFileInfo) throws IOException, InterruptedException {Integer currentChunk = uploadFileInfo.getCurrentChunk();Integer chunks = uploadFileInfo.getChunks();String fileName = uploadFileInfo.getFileName();// 如果当前分片等于总分片那么合并文件if (currentChunk != null && chunks != null && currentChunk.equals(chunks - 1)) {File tempFile = new File(uploadPath, fileName);try (BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(tempFile))) {// 根据之前命名规则找到所有分片for (int i = 0; i < chunks; i++) {File file = new File(uploadPath, i + "_" + fileName);// 并发情况,需要判断所有,因为可能最后一个分片传完,之前有的还没传完while (!file.exists()) {// 不存在休眠100毫秒后在重新判断Thread.sleep(100);}// 分片存在,读入数组中byte[] bytes = FileUtils.readFileToByteArray(file);os.write(bytes);os.flush();file.delete();}os.flush();}}}/*** 文件下载** @param request* @param response* @throws IOException*/public void download(HttpServletRequest request, HttpServletResponse response) throws IOException {// 获取文件File file = new File(downloadFile);// 获取下载文件信息DownloadFileInfo downloadFileInfo = getDownloadFileInfo(file.length(), request, response);// 设置响应头setResponse(response, file.getName(), downloadFileInfo);// 下载文件try (InputStream is = new BufferedInputStream(new FileInputStream(file));OutputStream os = new BufferedOutputStream(response.getOutputStream())) {// 跳过已经读取文件is.skip(downloadFileInfo.getPos());byte[] buffer = new byte[1024];long sum = 0;// 读取while (sum < downloadFileInfo.getRangeLength()) {int length = is.read(buffer, 0, (downloadFileInfo.getRangeLength() - sum) <= buffer.length ? (int) (downloadFileInfo.getRangeLength() - sum) : buffer.length);sum = sum + length;os.write(buffer, 0, length);}}}/*** 有两个map,我要去判断里面相同键的值一致不一致,除了双重for循环,有没有别的好办法*/private DownloadFileInfo getDownloadFileInfo(long fSize, HttpServletRequest request, HttpServletResponse response) {long pos = 0;long last = fSize - 1;// 判断前端是否需要分片下载if (request.getHeader(RANGE) != null) {response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);String numRange = request.getHeader(RANGE).replace("bytes=", "");String[] strRange = numRange.split("-");if (strRange.length == 2) {pos = Long.parseLong(strRange[0].trim());last = Long.parseLong(strRange[1].trim());// 若结束字节超出文件大小,取文件大小if (last > fSize - 1) {last = fSize - 1;}} else {// 若只给一个长度,开始位置一直到结束pos = Long.parseLong(numRange.replace("-", "").trim());}}long rangeLength = last - pos + 1;String contentRange = "bytes " + pos + "-" + last + "/" + fSize;return new DownloadFileInfo(fSize, pos, last, rangeLength, contentRange);}/*** 分片下载** @throws IOException*/public void downloads() throws IOException {File file = new File(downloadPath);// 如果文件夹不存在则创建if (!file.exists() && !file.isDirectory()) {file.mkdirs();}// 探测下载,获取文件相关信息FileInfo fileInfoDto = sliceDownload(1, 10, -1, null);// 如果不为空,执行分片下载if (fileInfoDto != null) {// 计算有多少分片long pages = fileInfoDto.getFileSize() / PER_SLICE;// 适配最后一个分片for (long i = 0; i <= pages; i++) {long start = i * PER_SLICE;long end = (i + 1) * PER_SLICE - 1;executorService.execute(new SliceDownloadRunnable(start, end, i, fileInfoDto.getFileName()));}}}/*** 分片下载** @param start 分片起始位置* @param end   分片结束位置* @param page  第几个分片, page=-1时是探测下载*/private FileInfo sliceDownload(long start, long end, long page, String fName) throws IOException {// 断点下载File file = new File(downloadPath, page + "-" + fName);// 如果当前文件已经存在,并且不是探测任务,并且文件的长度等于分片的大小,那么不用下载当前文件if (file.exists() && page != -1 && file.length() == PER_SLICE) {return null;}// 创建HttpClientHttpClient client = HttpClients.createDefault();HttpGet httpGet = new HttpGet("http://localhost:8018/file/download");httpGet.setHeader(RANGE, "bytes=" + start + "-" + end);HttpResponse httpResponse = client.execute(httpGet);String fSize = httpResponse.getFirstHeader("fSize").getValue();fName = URLDecoder.decode(httpResponse.getFirstHeader("fName").getValue(), UTF_8);HttpEntity entity = httpResponse.getEntity();// 下载try (InputStream is = entity.getContent();FileOutputStream fos = new FileOutputStream(file)) {byte[] buffer = new byte[1024];int ch;while ((ch = is.read(buffer)) != -1) {fos.write(buffer, 0, ch);}fos.flush();}// 判断是否是最后一个分片,如果是那么合并if (end - Long.parseLong(fSize) > 0) {mergeFile(fName, page);}return new FileInfo(Long.parseLong(fSize), fName);}private void mergeFile(String fName, long page) throws IOException {File file = new File(downloadPath, fName);try (BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file))) {for (int i = 0; i <= page; i++) {File tempFile = new File(downloadPath, i + "-" + fName);// 文件不存在或文件没写完while (!tempFile.exists() || (i != page && tempFile.length() < PER_SLICE)) {Thread.sleep(100);}byte[] bytes = FileUtils.readFileToByteArray(tempFile);os.write(bytes);os.flush();tempFile.delete();}// 删除文件File f = new File(downloadPath, "-1" + "-null");if (f.exists()) {f.delete();}} catch (InterruptedException e) {e.printStackTrace();}}private class SliceDownloadRunnable implements Runnable {private final long start;private final long end;private final long page;private final String fName;private SliceDownloadRunnable(long start, long end, long page, String fName) {this.start = start;this.end = end;this.page = page;this.fName = fName;}@Overridepublic void run() {try {sliceDownload(start, end, page, fName);} catch (IOException e) {e.printStackTrace();}}}/*** 设置响应头*/private void setResponse(HttpServletResponse response, String fileName, DownloadFileInfo downloadFileInfo) throws UnsupportedEncodingException {response.setCharacterEncoding(UTF_8);response.setContentType("application/x-download");response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, UTF_8));// 支持分片下载response.setHeader("Accept-Range", "bytes");response.setHeader("fSize", String.valueOf(downloadFileInfo.getFSize()));response.setHeader("fName", URLEncoder.encode(fileName, UTF_8));// range响应头response.setHeader("Content-Range", downloadFileInfo.getContentRange());response.setHeader("Content-Length", String.valueOf(downloadFileInfo.getRangeLength()));}}

5..编写上传文件实体类、文件信息实体类和下载文件实体类

package com.liyh.entity;import lombok.Data;@Data
public class UploadFileInfo {/*** 文件名称*/private String fileName;/*** 上传文件会有多个分片,记录当前为那个分片*/private Integer currentChunk;/*** 总分片数*/private Integer chunks;}
package com.liyh.entity;import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
@NoArgsConstructor
public class FileInfo {private long fileSize;private String fileName;}
package com.liyh.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@AllArgsConstructor
@NoArgsConstructor
@Data
public class DownloadFileInfo {/*** 文件总大小*/private long fSize;/*** 断点起始位置*/private long pos;/*** 断点结束位置*/private long last;/*** rang响应*/private long rangeLength;/*** range响应*/private String contentRange;}

运行效果

相关文章:

SpringBoot实现的大文件上传

前言 大文件分片上传和断点续传是为了解决在网络传输过程中可能遇到的问题&#xff0c;以提高文件传输的效率和稳定性。 首先&#xff0c;大文件分片上传是将大文件分割成较小的片段进行上传。这样做的好处是可以减少单个文件的传输时间&#xff0c;因为较小的文件片段更容易快…...

【Python高级编程】用 Matplotlib 绘制迷人的图表

用 Matplotlib 绘制迷人的图表 引言 Matplotlib 是 Python 中广泛使用的绘图库&#xff0c;用于创建各种图表和可视化。本文将逐步指导您使用 Matplotlib 绘制基本图表&#xff0c;包括折线图、条形图和散点图。 安装 Matplotlib 使用 pip 安装 Matplotlib&#xff1a; pi…...

【UML用户指南】-19-对基本行为建模-用例图

目录 1、组成结构 2、表示法 3、一般用法 3.1、对主题的语境建模 3.2、对主题的需求建模 4、常用建模技术 4.1、对系统的语境建模 4.1.1、设计过程 4.2、对系统的需求建模 4.2.1、设计过程&#xff1a; 5、正向工程 UML 中的用例图是对系统的动态方面建模的 5 种图之…...

mysql密码过期的修改(Your password has expired. ..)

参考文章&#xff1a;mysql密码过期的修改方法&#xff08;your password has expired&#xff09;_我是知青-RuoYi 若依 (csdn.net) 问题&#xff1a;Your password has expired. To log inyou must change it using a clientthat supports expired passwords. 解决方式&…...

vivado SLR

描述 超级逻辑区&#xff08;SLR&#xff09;是包含在堆叠硅中的单个FPGA芯片 互连&#xff08;SSI&#xff09;设备。堆叠式硅互连&#xff08;SSI&#xff09;技术使用无源硅 具有微凸块和硅通孔&#xff08;TSV&#xff09;的内插器&#xff0c;用于组合多个FPGA管芯 切片&a…...

【CSS】深入了解圆角属性border-radius

border-radius 是 CSS 中的一个非常有用的属性&#xff0c;它允许你创建具有圆角边框的元素。这个属性可以应用于一个元素的四个角&#xff0c;或者分别应用于每个角。下面我们将深入了解 border-radius 的使用方法和一些高级技巧。 基本用法 你可以通过为 border-radius 指定…...

LabVIEW与C#的区别及重新开发自动测试程序的可行性分析

LabVIEW和C#是两种广泛使用的编程语言&#xff0c;各自有不同的应用领域和特点。本文将详细比较LabVIEW与C#在自动测试程序开发中的区别&#xff0c;并分析将已完成的LabVIEW自动测试程序重新用C#开发的合理性。本文帮助评估这种转换的必要性和潜在影响。 LabVIEW与C#的区别 开…...

人工智能—美国加利福尼亚州房价预测实战

引言 在当今快速发展的房地产市场中&#xff0c;房价预测已成为一个至关重要的领域。它不仅关系到投资者的决策&#xff0c;也直接影响到普通购房者的生活质量。特别是在美国加利福尼亚州&#xff0c;这个以其高房价和房地产市场的波动性而闻名的地方&#xff0c;准确的房价预…...

python pandas处理股票量化数据:笔记2

有一个同学用我的推荐链接注册了tushare社区帐号https://tushare.pro/register?reg671815&#xff0c;现在有了170分积分。目前使用数据的频率受限制。不过可以在调试期间通过python控制台获取数据&#xff0c;将数据保存在本地以后使用不用高频率访问tushare数据接口&#xf…...

enum库

Python enum 模块教程 enum 是 Python 3.4 引入的一个模块&#xff0c;用于定义枚举类型。枚举类型是一种特殊的数据类型&#xff0c;由一组命名的值组成&#xff0c;这些值称为枚举成员。使用 enum 可以提高代码的可读性和可维护性&#xff0c;特别是在处理一组相关的常量值时…...

【CT】LeetCode手撕—141. 环形链表

目录 题目1- 思路2- 实现⭐141. 环形链表——题解思路 3- ACM实现 题目 原题连接&#xff1a;141. 环形链表 1- 思路 模式识别 模式1&#xff1a;判断链表的环 ——> 快慢指针 思路 快指针 ——> 走两步慢指针 ——> 走一步判断环&#xff1a;若快慢相遇则有环&a…...

python,自定义token生成

1、使用的包PyJWT来实现token生成 安装&#xff1a;pip install PyJWT2.8.0 2、使用例子&#xff1a; import jwt import time pip install pyJWT2.8.0 SECRET_KEY %^ES*E&Ryurehuie9*7^%$#$EDFGHUYTRE#$%^&%$##$RTYGHIK DEFAULT_EXP 7 * 24 * 60def create_token(…...

小米SU7遇冷,下一代全新车型被官方意外曝光

不知道大伙儿有没有发现&#xff0c;最近小米 SU7 热度好像突然之间就淡了不少&#xff1f; 作为小米首款车型&#xff0c;SU7 自上市以来一直承载着新能源轿车领域流量标杆这样一个存在。 发售 24 小时订单量破 8 万&#xff0c;2 个月后累计交付破 2 万台。 看得出来限制它…...

JavaScript 函数与事件

1. JavaScript自定义函数 语法&#xff1a; function 函数名&#xff08;参数列表&#xff09;{ 方法体; } 在函数被调用时&#xff0c;一个 arguments 对象就会被创建&#xff0c;它只能使用在函数体中&#xff0c;以数组的形式来管理函数的实际…...

Qt 焦点系统关键点总结

1.1 焦点窗口 指的是当前时刻拥有键盘输入的窗口。 Qt提供了如下接口&#xff0c;用于设置窗口是否是”可获取焦点“窗口&#xff1a; void QWidget::setFocusPolicy(Qt::FocusPolicy policy); Qt::FocusPolicy Qt::TabFocus 与焦点链相关&#xff0c;详解见下一…...

SpringBoot+Maven项目的配置构建

文章目录 1、application.properties2、pom.xml 1、application.properties 也可使用yml yaml #静态资源 spring.mvc.static-path-pattern/images/** #上传文件大小设置 spring.http.multipart.max-file-size10MB spring.http.multipart.max-request-size10MBspring.mvc.path…...

c#调用c++dll方法

添加dll文件到debug目录&#xff0c;c#生成的exe的相同目录 就可以直接使用了&#xff0c;放在构造函数里面测试...

ACM算法学习路线、清单

入门 模拟、暴力、贪心、高精度、排序 图论 搜索 BFS、DFS、IDDFS、IDA*、A*、双向BFS、记忆化 最短路 SPFA、bellman-fort(队列优化)、Dijkstra(堆优化)、Johnson、Floyd、差分约束、第k短路 树 树的重心和直径、dfs序、树链刨分与动态树、LCA、Prufer编码及Cayley定理…...

sqoop的安装配置

1. 上传并解压安装包 tar -zxvf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C ../server/ 重命名&#xff1a;mv sqoop-1.4.7.bin__hadoop-2.6.0 sqoop 2. 配置环境变量 sudo vim /etc/profile # 配置sqoop的环境变量 export SQOOP_HOME/export/server/sqoop export PATH$PATH…...

代码随想录算法训练营第六十四天 | 图论理论基础、深搜理论基础、广搜理论基础、98. 所有可达路径

图论理论基础 我写在了个人语雀笔记中 https://www.yuque.com/yuqueyonghu8mml9e/bmbl71/ex473q4y0ebs0l3r?singleDoc# 深搜理论基础 https://www.yuque.com/yuqueyonghu8mml9e/bmbl71/zamfikz08c2haptn?singleDoc# 98. 所有可达路径 题目链接&#xff1a;98. 所有可达…...

【教师资格证考试综合素质——法律专项】教师法笔记以及练习题

《中华人民共和国教师法》 一&#xff0e;首次颁布&#xff1a;第一部《中华人民共和国教师法》于1993年10月31日由第八届全国人民代表大会常务委员会第四次会议通过&#xff0c;1994年1月1日起执行。 二&#xff0e;历次修改&#xff1a;2009年8月27日第十一届全国人民代表…...

图卷积网络(Graph Convolutional Network, GCN)

图卷积网络&#xff08;Graph Convolutional Network, GCN&#xff09;是一种用于处理图结构数据的深度学习模型。GCN编码器的核心思想是通过邻接节点的信息聚合来更新节点表示。 图的表示 一个图 G通常表示为 G(V,E)&#xff0c;其中&#xff1a; V 是节点集合&#xff0c;…...

【diffusers 极速入门(一)】pipeline 实际调用的是什么? __call__ 方法!

在使用 diffusers 库进行图像生成时&#xff0c;你可能会发现管道&#xff08;pipeline&#xff09;对象可以像函数一样被调用。这背后的魔法是什么呢&#xff1f;答案是&#xff1a;__call__ 方法&#xff01;本文将通过简单的案例代码&#xff0c;带你快速了解 diffusers 管道…...

【DPDK学习路径】二、DPDK简介

DPDK(Data Plane Development Kit)是一个框架&#xff0c;用于快速报文处理。 在linux内核提供的报文处理模型中&#xff0c;接收报文的处理路径为&#xff1a;首先由网卡硬件接收&#xff0c;产生硬中断&#xff0c;触发网卡驱动程序注册的中断函数处理&#xff0c;之后产生软…...

python基础 002 - 2 常用数据类型

python的常用数据类型 int , 整型 1,2,3float ,小数&#xff0c;浮点类型1.2bool , boolean 布尔&#xff0c;真假。判断命题。True Flasestr &#xff0c;字符串 list , 列表 a []tuple, 元组 a ()dict , dictionary, 字典 a {}set , 集合 a {} 1 查看数据类型 typ…...

爆赞!GitHub首本Python开发实战背记手册,标星果然百万名不虚传

Python (发音:[ paiθ(ə) n; (US) paiθɔn ] n. 蟒蛇&#xff0c;巨蛇 )&#xff0c;是一种面向对象的解释性的计算机程序设计语言&#xff0c;也是一种功能强大而完善的通用型语言&#xff0c;已经具有十多年的发展历史&#xff0c;成熟且稳定。Python 具有脚本语言中最丰富…...

Spring源码-xxxAware实现类和BeanPostProcessor接口调用过程

xxxAware实现类作用 以ApplicationContextAware接口为例 ApplicationContextAware的作用是可以方便获取Spring容器ApplicationContext&#xff0c;从而可以获取容器内的Bean package org.springframework.context;import org.springframework.beans.BeansException; import or…...

Uni-app x

uni-app x&#xff0c;是下一代 uni-app&#xff0c;是一个跨平台应用开发引擎。 uni-app x 是一个庞大的工程&#xff0c;它包括uts语言、uvue渲染引擎、uni的组件和API、以及扩展机制。 uts是一门类ts的、跨平台的、新语言。uts在iOS端编译为swift、在Android端编译为kotli…...

Python 基础:文件

目录 一、从文件中读取数据1.1 读取整个文件1.2 逐行读取 二、写入文件2.1 写入空文件2.2 写入多行2.3 附加到文件 遇到看不明白的地方&#xff0c;欢迎在评论中留言呐&#xff0c;一起讨论&#xff0c;一起进步&#xff01; 本文参考&#xff1a;《Python编程&#xff1a;从入…...

WebForms 母版页

WebForms 母版页 介绍 WebForms 母版页是 ASP.NET WebForms 应用程序中的一项功能&#xff0c;它允许开发人员创建一个包含页面布局和控件的模板&#xff0c;其他页面可以继承这个模板。使用母版页可以确保整个网站的一致性和减少重复代码。 如何创建母版页 在 Visual Stud…...

wordpress trac/刷粉网站推广快点

深度学习和强化学习之间的结合给人工智能带来了无数的机会。然而&#xff0c;稀疏的奖励环境对强化学习的研究者而言是一个需要长期面临的挑战。在不提供信息的奖励信号上设定参数通常会使学习收敛到次优策略。DeepMind的Unsupervised Reinforcement and Auxiliary Learning (简…...

网络营销的特点哪四个/长沙seo顾问

在 Windows XP 系统中&#xff0c;某些情况下可能会出现任务栏工作不正常的情况&#xff0c;比如&#xff1a;任务栏不显示正在运行的程序的图标&#xff0c;或者在任务栏上总是出现重复的图标。要解决这类问题&#xff0c;可以尝试如下方法&#xff1a;按下 CtrlAltDel 键&…...

网站网页直播怎么做的/什么是软文营销?

文章目录为什么不相等如何解决方法一方法二js中如何处理bignumBigInt为什么不相等 从小我们就知道0.1 0.20.3。但是&#xff0c;在光怪陆离的计算世界中&#xff0c;运算方式却大相径庭。 0.1加0.2为什么就不等于0.3呢&#xff1f;要回答这个问题&#xff0c;得先了解计算机…...

怎么用dw第一次做网站/广东seo推广哪里好

一个ip可以对应多个域名&#xff0c;比如现有&#xff1a;www.abc.com,需要增加test.abc.com先在域名解析中&#xff0c;添加A记录,主机记录为test,记录值和www的记录值一样服务器中80端口设置为nginx&#xff0c;nginx.conf配置如下&#xff1a;server {listen 80;server_name…...

网站如何做生僻词引流/适合女生去的培训机构

今天通过scratch课程制作一个小游戏&#xff0c;童年经典游戏之《打砖块》 先来看看成品制作完成后的体验视频 现在开始进行我们的编程之旅 首先&#xff0c;打开scratch软件&#xff0c;在角色区选择三个角色&#xff0c;分别是小球、挡板和砖块。 今天通过scratch课程制作一个…...

吴中区做网站/软文广告投放平台

├1.初识JVM.mp4├2.JVM运行机制.mp4├3.常用JVM配置参数.mp4├4.GC算法与种类.mp4├5.GC参数.mp4├6.类装载器.mp4├7.性能监控工具.mp4├8.Java堆分析.mp4├9.锁.mp4├10.Class文件结构.mp4├11.字节码执行.mp4├│ ├JVM的垃圾回收机制详解和调优.docx│ ├深入Java核心 J…...