django连接minio实现文件上传下载(提供接口示例)

  • 项目环境前提
  • 1.模型创建
  • 2. 在 settings.py 中添加 MINIO 配置
  • 3.创建 MINIO 工具类
  • 4.创建序列化器
  • 5. 创建视图
  • 6. 配置 URL 路由
  • 7.接口测试

项目环境前提

  1. 已安装python3.8+以上环境
  2. 已安装djangorestframework环境
  3. 已部署mysql数据库
  4. 已部署minio
  5. 所需python依赖:django-storages、minio

1.模型创建

1.这里模型创建的前提是DRF的项目框架已搭建好。创建文件上传模型字段如下所示
注:这里只展示文件上传等字段,去除了其他字段,实际开发根据项目需求添加

# 这里仅介绍文件上传,所以只展示文件上传所需字段
class ApprovalProcess(models.Model):  minio_url172_1 = models.TextField(null=True, blank=True, verbose_name='url172_1')minio_url10_1 = models.TextField(null=True, blank=True, verbose_name='url10_1')minio_source_name_1 = models.CharField(null=True, blank=True, max_length=200, verbose_name='源文件名1')minio_file_name_1 = models.TextField(null=True, blank=True, verbose_name='minio文件名1')create_time = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name='创建时间')update_time =  models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name='更新时间')is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')def delete(self, using=None, keep_parents=False):# 逻辑删除# 把当前模型对象的is_delete字段改为True即可self.is_delete = Trueself.save()# 配置后台管理系统每个模型的名字显示class Meta:db_table = 'approval_process'verbose_name = '审批流程表' verbose_name_plural = verbose_nameindexes = [models.Index(fields=['minio_url172_1','minio_url10_1']),]

2. 在 settings.py 中添加 MINIO 配置

# MinIO 配置信息 
# 这里有两个网段IP地址,所以配置了两个,只有一个IP的看情况配置
MINIO_STORAGE_ENDPOINT_172 = '172.xx.xx.xxx:5096'  # MinIO 服务器地址1
MINIO_STORAGE_ENDPOINT_10 = '10.xx.xx.xxx:5096'  # MinIO 服务器地址2
MINIO_STORAGE_ACCESS_KEY = 'minio账号'  # 你的minio账号
MINIO_STORAGE_SECRET_KEY = 'minio账号密码'  # 你的minio账号密码
MINIO_STORAGE_USE_HTTPS = False  # 如果未启用 HTTPS,则为 False
MINIO_STORAGE_MEDIA_BUCKET_NAME = 'backstickerv3'  # 用于存储文件的桶名称,前提是已在minio创建好这个文件桶

3.创建 MINIO 工具类

  1. 在ApprovalProcess模型下创建utils文件,在该文件下创建monio_utils.py的文件,用于处理minio的文件上传和下载
    在这里插入图片描述
  2. 代码如下。共三个主要函数:
    1)upload_file:处理文件上传
    2)download_file:处理文件直接下载
    3)get_presigned_url:生成预签名URL,处理文件下载
    下载文件时可根据需求选择使用download_file或者get_presigned_url
# apps/ApprovalProcess/utils/minio_utils.py
from minio import Minio
from minio.error import S3Error
from django.conf import settings
import uuid
import os
import logging
from django.http import HttpResponse
from django.http import StreamingHttpResponse
import mimetypes  # 用于根据文件名猜测 MIME 类型
import urllib.parse
from datetime import timedelta 
# 配置日志
logger = logging.getLogger(__name__)class MinioClient:"""MinIO 操作工具类"""def __init__(self):# 从配置中获取端点,移除协议头#要确保这些值是字符串,可以打印查看endpoint_172 = settings.MINIO_STORAGE_ENDPOINT_172.replace('http://', '').replace('https://', '')endpoint_10 = settings.MINIO_STORAGE_ENDPOINT_10.replace('http://', '').replace('https://', '')access_key=settings.MINIO_STORAGE_ACCESS_KEYsecret_key=settings.MINIO_STORAGE_SECRET_KEYsecure=settings.MINIO_STORAGE_USE_HTTPS# 初始化 172 网段客户端self.client_172 = Minio(endpoint=endpoint_172,  # 使用一个端点access_key=access_key,secret_key=secret_key,secure=secure)# 初始化 10 网段客户端self.client_10 = Minio(endpoint=endpoint_10,access_key=access_key,secret_key=secret_key,secure=secure)logger.info(f"MinIO clients initialized for both networks: 172 - {endpoint_172}, 10 - {endpoint_10}")# def upload_file(self, file_obj, file_name, bucket_name, content_type='application/octet-stream'):def upload_file(self, file_obj, file_name, bucket_name, content_type='message/rfc822'):"""上传文件到 MinIOArgs:file_obj: 文件对象(如 Django 的 UploadedFile)file_name: 希望在 MinIO 中存储的文件名bucket_name: 存储桶名称content_type: 文件类型Returns:dict: 包含文件访问 URL 等信息的字典"""# 生成唯一的对象名称,避免覆盖file_extension = os.path.splitext(file_name)[1]unique_filename = f"{uuid.uuid4().hex}{file_extension}"object_name = f"approval_uploads/{unique_filename}"  # 可以添加前缀分类try:# 确保存储桶存在if not self.client_172.bucket_exists(bucket_name):self.client_172.make_bucket(bucket_name)logger.info(f"Bucket '{bucket_name}' created.")# 获取文件大小# 对于 Django 的 UploadedFile,可以使用 file_obj.sizefile_size = file_obj.size# 上传文件self.client_172.put_object(bucket_name,object_name,file_obj,file_size,content_type=content_type)# 构建文件的访问 URL(路径风格)# 添加协议头(http 或 https)protocol = "https" if settings.MINIO_STORAGE_USE_HTTPS else "http"url_172 = f"{protocol}://172.xx.xx.xxx:5096/{bucket_name}/{object_name}"url_10 = f"{protocol}://10.xx.xx.xxx:5096/{bucket_name}/{object_name}"logger.info(f"File uploaded successfully: {object_name}")return {"url_172_1": url_172,"url_10_1": url_10,"file_name": unique_filename,"original_name": file_name,"object_name": object_name}except S3Error as e:logger.error(f"MinIO S3Error occurred: {e}")raise eexcept Exception as e:logger.error(f"Unexpected error during MinIO upload: {e}")raise edef download_file(self, bucket_name, object_name, file_name):"""从 MinIO 下载文件Args:bucket_name: 存储桶名称object_name: 对象名称(在 MinIO 中的路径)file_name: 下载时显示的文件名Returns:HttpResponse: 包含文件数据的 HTTP 响应"""try:# print('file_name=', file_name)# 从 MinIO 获取文件数据response = self.client_172.get_object(bucket_name, object_name)file_data = response.read()response.close()response.release_conn()# # 确保文件名有正确的扩展名# if not file_name.lower().endswith('.eml'):#     # 如果文件名没有 .eml 扩展名,添加它#     file_name = f"{file_name}.eml"# 对文件名进行 URL 编码,确保特殊字符正确处理encoded_filename = urllib.parse.quote(file_name)# 创建 HTTP 响应 - 使用正确的 Content-Typecontent_type = 'message/rfc822'  # .eml 文件的正确 MIME 类型http_response = HttpResponse(file_data, content_type=content_type)# 设置 Content-Disposition 头,确保浏览器正确下载文件# 使用 filename* 参数并指定 UTF-8 编码来处理可能包含非 ASCII 字符的文件名http_response['Content-Disposition'] = f'attachment; filename="{encoded_filename}"; filename*=UTF-8\'\'{encoded_filename}'# 设置 Content-Lengthhttp_response['Content-Length'] = len(file_data)logger.info(f"File downloaded successfully: {object_name}")return http_responseexcept S3Error as e:logger.error(f"MinIO S3Error occurred during download: {e}")raise eexcept Exception as e:logger.error(f"Unexpected error during MinIO download: {e}")raise edef get_presigned_url(self, bucket_name, object_name, filename=None, expiry=3600, network='both'):"""生成预签名 URL(支持双网段)Args:bucket_name: 存储桶名称object_name: 对象名称expiry: URL 有效期(秒),默认 1 小时network: 网络类型,'172'、'10' 或 'both'Returns:str 或 dict: 预签名 URL 或包含两个 URL 的字典"""try:# 将秒数转换为 timedelta 对象expires_td = timedelta(seconds=expiry)# 构建响应头参数(如果提供了自定义文件名)extra_query_params = {}# print('filename=',filename)if filename:# 对文件名进行 URL 编码encoded_filename = urllib.parse.quote(filename)# 添加响应内容处置参数,指定下载文件名extra_query_params['response-content-disposition'] = f'attachment; filename="{encoded_filename}"'# print('network=',network)if network == 'both':# 生成两个网段的 URLurl_172 = self.client_172.presigned_get_object(bucket_name, object_name, expires=expires_td,extra_query_params=extra_query_params)url_10 = self.client_10.presigned_get_object(bucket_name, object_name, expires=expires_td,extra_query_params=extra_query_params)result = {'url_172': url_172,'url_10': url_10}return resultelif network == '10':# 只生成 10 网段的 URLurl_10 = self.client_10.presigned_get_object(bucket_name, object_name, expires=expires_td,extra_query_params=extra_query_params)result = {'url_172': '','url_10': url_10}return resultelse:# 默认生成 172 网段的 URLurl_172 = self.client_172.presigned_get_object(bucket_name, object_name, expires=expires_td,extra_query_params=extra_query_params)result = {'url_172': url_172,'url_10': ''}return resultexcept S3Error as e:logger.error(f"MinIO S3Error occurred generating presigned URL: {e}")raise eexcept Exception as e:logger.error(f"Unexpected error generating presigned URL: {e}")raise e   # 创建全局 MinIO 客户端实例
minio_client = MinioClient()

4.创建序列化器

  1. 创建处理文件上传的序列化器:ApprovalProcessCreateSerializer,重写 create 方法
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer
from .models import *
from django.core.validators import FileExtensionValidatorclass ApprovalProcessCreateSerializer(serializers.ModelSerializer):# 注意:这个字段仅用于接收上传的文件,不会保存在模型中(write_only=True)# upload_file = serializers.FileField(write_only=True, required=False, label="上传文件")upload_file = serializers.FileField(write_only=True,required=False,validators=[FileExtensionValidator(allowed_extensions=['eml', 'doc', 'docx','xlsx']),  # 允许的文件后缀# 还可以自定义验证函数限制文件大小],label="上传文件")class Meta:model = ApprovalProcess# 排除一些字段,这些字段将通过逻辑自动填充,而不是由用户输入exclude = ['is_delete', 'create_time', 'update_time', 'minio_url172_1', 'minio_url10_1', 'minio_source_name_1', 'minio_file_name_1']def create(self, validated_data):"""重写 create 方法,处理文件上传和模型创建"""# 1. 从验证后的数据中弹出文件数据(如果存在)uploaded_file = validated_data.pop('upload_file', None)# 2. 创建 ApprovalProcess 模型实例(先不保存文件相关信息)instance = ApprovalProcess.objects.create(**validated_data)# 3. 如果上传了文件,则处理 MinIO 上传if uploaded_file:try:from .utils.minio_utils import minio_client  # 在函数内部导入,避免循环导入# 调用 MinIO 工具类上传文件upload_result = minio_client.upload_file(file_obj=uploaded_file,file_name=uploaded_file.name,bucket_name='backstickerv3'  # 确保与 settings 中的桶名一致,或从设置中读取)# 4. 更新实例的 MinIO 相关字段instance.minio_url172_1 = upload_result['url_172_1']instance.minio_url10_1 = upload_result['url_10_1']instance.minio_source_name_1 = upload_result['original_name']instance.minio_file_name_1 = upload_result['file_name']instance.save()  # 保存文件信息到数据库except Exception as e:# 处理文件上传失败的情况# 这里可以选择记录日志、删除刚创建的实例,或者保留实例但标记文件上传失败# 例如:instance.file_upload_error = str(e); instance.save()# 暂时打印错误,生产环境应使用日志系统print(f"File upload failed for instance {instance.id}: {str(e)}")# 即使文件上传失败,也返回实例,但可能缺少文件信息return instance

5. 创建视图

  1. 实现创建数据的接口:create_data
    注:这里的create_data包含了其他字段的校验并创建了操作记录,根据实际情况来的,不只是处理文件上传,如果想验证文件上传的,把其他数据的校验去除即可。
  2. 实现文件下载的接口:download_file
  3. 实现获取文件下载链接(预签名 URL)的接口:get_download_url
from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status
import re,os,random
import datetime,time
from .serializers import *
from .models import *
from django.conf import settings
from django.shortcuts import get_object_or_404
from django.http import StreamingHttpResponse
# from django.utils.http import urlquote
from urllib.parse import quote
from django.db.models import Q
from datetime import timedelta,date
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from datetime import timedelta,date
from django.db import transaction
import requests
from django.utils import timezone
from rest_framework.pagination import PageNumberPagination
from django.db import transaction
import logging
import MySQLdb
from django.db.models import Subquery, OuterRef, Exists
# 配置日志
logger = logging.getLogger(__name__)class CustomPagination(PageNumberPagination):page_size = 20  # 设置每页数据量page_size_query_param = 'page_size'  # 允许客户端传递页面大小参数max_page_size = 100  # 最大页面大小限制class ApprovalProcessViewSet(viewsets.ModelViewSet):  # ctrl+点击ModelViewSet可以查看源代码queryset = ApprovalProcess.objects.filter(is_delete=False)  # 定义视图集使用的查询集serializer_class = ApprovalProcessSerializer  # 定义视图集使用的序列化器@action(methods=['post'], detail=False)def create_data(self, request):"""处理 POST 请求,创建审批流程数据(带字段校验和事务回滚)。Request Body (multipart/form-data 或 application/json):- 包含 ApprovalProcess 模型的字段(如 project, line, responser 等)- upload_file (可选): 要上传的文件Returns:- 201 Created: 成功创建,返回创建的数据(包括文件URL,如果上传了文件)- 400 Bad Request: 数据验证失败,返回错误信息- 500 Internal Server Error: 服务器内部错误(如MinIO连接失败)"""# 1. 使用序列化器验证和解析请求数据serializer = ApprovalProcessCreateSerializer(data=request.data)if not serializer.is_valid():return Response({"success": False,"message": "数据验证失败","errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)# 2. 手动验证必填字段required_fields = ['project', 'line', 'by_class', 'task', 'pro_code', 'work_order', 'responser', 'lose_reason', 'improve_method', 'status', 'custom_name']missing_fields = []for field in required_fields:if field not in serializer.validated_data or not serializer.validated_data[field]:missing_fields.append(field)if missing_fields:return Response({"success": False,"message": "以下字段为必填项且不能为空","missing_fields": missing_fields}, status=status.HTTP_400_BAD_REQUEST)# 3. 开始事务with transaction.atomic():# 创建保存点sid = transaction.savepoint()try:# 4. 从验证数据中提取文件(如果存在)validated_data = serializer.validated_data.copy()uploaded_file = validated_data.pop('upload_file', None)# 5. 创建 ApprovalProcess 模型实例(先不包含文件信息)instance = ApprovalProcess.objects.create(**validated_data)# 6. 如果上传了文件,则处理 MinIO 上传if uploaded_file:try:from .utils.minio_utils import minio_client# 调用 MinIO 工具类上传文件upload_result = minio_client.upload_file(file_obj=uploaded_file,file_name=uploaded_file.name,bucket_name='backstickerv3')# 7. 更新实例的 MinIO 相关字段instance.minio_url172_1 = upload_result['url_172_1']instance.minio_url10_1 = upload_result['url_10_1']instance.minio_source_name_1 = upload_result['original_name']instance.minio_file_name_1 = upload_result['file_name']instance.save()except Exception as e:# 文件上传失败,回滚事务transaction.savepoint_rollback(sid)logger.error(f"文件上传失败: {str(e)}")return Response({"success": False,"message": f"文件上传失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)else:# 如果没有上传文件,回滚事务transaction.savepoint_rollback(sid)logger.error("文件未上传,数据创建失败")return Response({"success": False,"message": "必须上传文件才能创建数据"}, status=status.HTTP_400_BAD_REQUEST)# 创建 FlowData 操作记录try:flow_data = FlowData.objects.create(P_id=instance.id,point=1,  # 默认节点,"生产创建"result=1,  # 默认处理结果,"提交"user=request.data['user'],  worknumber=request.data['worknumber'],  remark=request.data['remark']  # 可以根据实际情况调整备注)flow_data.save()except Exception as e:# 文件上传失败,回滚事务transaction.savepoint_rollback(sid)logger.error(f"操作记录失败: {str(e)}")return Response({"success": False,"message": f"操作记录失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)# 8. 提交事务transaction.savepoint_commit(sid)# 9. 构建成功的响应数据response_data = {"success": True,"message": "审批流程创建成功","data": {"id": instance.id,"project": instance.project,"task": instance.task,"status": instance.status,"create_time": instance.create_time,}}# 如果上传了文件,在响应中包括文件信息if instance.minio_url172_1:response_data["data"]["file_info"] = {"original_name": instance.minio_source_name_1,"url_172": instance.minio_url172_1,"url_10": instance.minio_url10_1}return Response(response_data, status=status.HTTP_201_CREATED)except Exception as e:# 回滚事务transaction.savepoint_rollback(sid)logger.error(f"创建审批流程失败: {str(e)}")return Response({"success": False,"message": f"服务器内部错误: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)@action(methods=['get'], detail=True)def download_file(self, request, pk=None):"""下载文件接口参数:pk: 审批流程记录的主键 ID返回:- 200 OK: 文件下载- 404 Not Found: 记录或文件不存在- 500 Internal Server Error: 服务器内部错误"""try:# 获取审批流程记录approval_process = self.get_object()# print('approval_process.minio_source_name_1=',approval_process.minio_source_name_1)# 检查文件是否存在if not approval_process.minio_file_name_1:return Response({"success": False,"message": "文件不存在"}, status=status.HTTP_404_NOT_FOUND)# 从 MinIO 下载文件from .utils.minio_utils import minio_client# 构建对象名称(与上传时一致)object_name = f"approval_uploads/{approval_process.minio_file_name_1}"# 下载文件response = minio_client.download_file(bucket_name='backstickerv3',object_name=object_name,# file_name=approval_process.minio_source_name_1 or f"file_{approval_process.id}"file_name=approval_process.minio_source_name_1)return responseexcept ApprovalProcess.DoesNotExist:return Response({"success": False,"message": "审批流程记录不存在"}, status=status.HTTP_404_NOT_FOUND)except Exception as e:logger.error(f"文件下载失败: {str(e)}")return Response({"success": False,"message": f"文件下载失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)@action(methods=['get'], detail=True)def get_download_url(self, request, pk=None):"""获取文件下载链接(预签名 URL)参数:pk: 审批流程记录的主键 ID返回:- 200 OK: 包含下载链接的响应- 404 Not Found: 记录或文件不存在- 500 Internal Server Error: 服务器内部错误"""try:# 获取审批流程记录approval_process = self.get_object()# print('approval_process=',approval_process.id)# 检查文件是否存在if not approval_process.minio_file_name_1:return Response({"success": False,"message": "文件不存在"}, status=status.HTTP_404_NOT_FOUND)# 从 MinIO 获取预签名 URLfrom .utils.minio_utils import minio_client# 构建对象名称(与上传时一致)object_name = f"approval_uploads/{approval_process.minio_file_name_1}"filename = approval_process.minio_source_name_1network = 'both' # 三个值:10 、172 、both:生成两个网段的 URL# 生成预签名 URL(有效期 1 小时)# print('filename=',filename)presigned_url = minio_client.get_presigned_url(bucket_name='backstickerv3',object_name=object_name,expiry=3600, # 1 小时network=network,filename=filename)return Response({"success": True,"message": "获取下载链接成功","data": {"download_url_172": presigned_url['url_172'],"download_url_10": presigned_url['url_10'],"expires_in": 3600,  # 有效期(秒)"file_name": approval_process.minio_source_name_1}}, status=status.HTTP_200_OK)except ApprovalProcess.DoesNotExist:return Response({"success": False,"message": "审批流程记录不存在"}, status=status.HTTP_404_NOT_FOUND)except Exception as e:logger.error(f"获取下载链接失败: {str(e)}")return Response({"success": False,"message": f"获取下载链接失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

6. 配置 URL 路由

  1. ApprovalProcess的APP下配置路由
from .views import *
from rest_framework.routers import DefaultRouter #导入默认路由器
from django.urls import path,includeurlpatterns = [
]
# 1.创建路由器
router = DefaultRouter() #有根路由
# 2.注册路由,有其他路由时,只需要注册进来即可
router.register('ApprovalProcess',ApprovalProcessViewSet)
# 3.得到生成的路由,只会自动生成标准的restful风格的增删改查功能接口路由
#查询单一:标准只会根据id来查询 写了id最后面要加/
urlpatterns += router.urls #添加到urlpatterns中即可
  1. 配置主路由
from django.contrib import admin
from django.urls import path,include
from rest_framework.documentation import include_docs_urlsurlpatterns = [path('admin/', admin.site.urls),path('docs/', include_docs_urls('接口文档')), #配置接口文档路由,文档标题path('api/', include('ApprovalProcess.urls')),]

7.接口测试

使用apifox进行接口测试

  1. 测试文件上传功能:调用create_data接口
    在这里插入图片描述
  2. 测试文件下载功能:调用download_file接口
    在这里插入图片描述
  3. 测试获取文件下载链接功能:调用get_download_url接口。浏览器访问链接可下载文件。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka消息队列进阶:发送策略与分区算法优化指南

Kafka消息队列进阶:发送策略与分区算法优化指南 目录Kafka消息队列进阶:发送策略与分区算法优化指南摘要1. Kafka消息发送模式概述1.1 消息发送的核心流程1.2 三种发送模式对比2. 同步发送模式详解2.1 同步发送实现原理2.2 同步发送性能优化3. 异步发送模…

【VScode】ssh报错

【VScode】ssh报错1. ssh报错2. 解决1. ssh报错 Failed to parse remote port from server output 2. 解决 windows电脑删除 C:\Users\username\.ssh\known_hosts linux cd /home/username/.vscode-server/ rm -rf ~/.vscode-server重新回到Vscode连接ok

Grafana+Loki+Alloy构建企业级日志平台

1.日志系统介绍日志系统:GLA、ELK、数仓 ⽇志处理流程:采集 > 存储 > 检索 > 可视化日志系统工作流程:日志平台的目的:统一聚合分散的日志日志平台搭建方案:ELK:ElasticSearch:存储日志&#xff0…

老梁聊全栈系列:(阶段一)现代全栈的「角色边界」与「能力雷达图」

JAVA Vue/React 双栈工程师的「T 型→E 型」进化指南 接上篇《从单体到云原生的演进脉络》 大家好,我是技术老梁,这是系列文章的第五篇。欢迎大家讨论,分享经验。如果知识对你有用,关注我,多多支持老梁,鼓…

使用 C# 设置 Excel 单元格格式

在实际报表开发中,Excel 的可读性和美观性与数据本身同样重要。合理的单元格格式设置不仅能让数据一目了然,还能让报表显得更专业。通过使用 C#,开发者可以精确控制 Excel 文件的单元格样式,无需依赖 Microsoft Office。 本文演示…

Redis篇章3:Redis 企业级缓存难题全解--预热、雪崩、击穿、穿透一网打尽

在企业级应用场景中,Redis 作为高性能缓存利器,极大提升了系统响应速度,但随着业务复杂度和并发量的攀升,缓存相关的各类挑战也接踵而至。比如系统启动时缓存缺失导致的数据库压力、大量缓存同时失效引发的连锁故障、热点数据过期…

【数值分析】02-绪论-误差

参考资料: 书籍: 数值分析简明教程/王兵团,张作泉,张平福编著. --北京:清华大学出版社;北京交通大学出版社,2012.8 视频:学堂在线APP中北京交通大学“数值分析I” 前期回顾 【数值分…

P3918 [国家集训队] 特技飞行

P3918 [国家集训队] 特技飞行 - 洛谷 思路: 因为如果连续进行相同的动作,乘客会感到厌倦,所以定义某次动作的价值为(距上次该动作的时间) ci​,若为第一次进行该动作,价值为 0。同一个动作,价值为ci*(最后一…

Python爬虫实战:研究Pandas,构建期货数据采集和分析系统

1. 引言 1.1 研究背景 期货市场作为金融市场的重要组成部分,具有价格发现、风险管理和资源配置的重要功能。上海期货交易所(Shanghai Futures Exchange, SHFE)作为中国四大期货交易所之一,上市交易的品种包括铜、铝、锌、黄金、白银等多种大宗商品期货,其交易数据反映了…

Linux第十七讲:应用层自定义协议与序列化

Linux第十七讲:应用层自定义协议与序列化1.什么是序列化和反序列化2.重新理解read、write为什么支持全双工3.网络版计算器的实现3.1socket的封装 -- 模板方法模式引入3.2序列化和反序列化 && json3.3协议的实现3.4 服务端整体看 -- 所有代码3.5七层协议&…

附录:Tomcat下载及启动

一、打开Tomcat官网windows下载第四个压缩包,下载完成后解压缩。(安装路径不要带有中文和特殊符号)二、启动Tomcat进入bin文件夹:\Tomcat\apache-tomcat-11.0.11\bin,找到startup.bat文件点击,黑窗口常驻即…

【CTF-WEB】表单提交(特殊参数:?url=%80和?url=@)(通过GBK编码绕过实现文件包含读取flag)

题目 寻找这个单纯的网站的flag 前端代码&#xff1a; <!DOCTYPE html> <head><title>CAT</title> </head><body> <h1>Cloud Automated Testing</h1> <p>输入你的域名&#xff0c;例如&#xff1a;loli.club</p>…

(k8s)Kubernetes 资源控制器关系图

Kubernetes 资源控制器关系图 #mermaid-svg-da6tzgmJn70StNQM {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-da6tzgmJn70StNQM .error-icon{fill:#552222;}#mermaid-svg-da6tzgmJn70StNQM .error-text{fill:#55222…

模电基础:场效应管

目录 一、场效应管概述 二、结型场效应管&#xff1a;基础场效应管 &#xff08;1&#xff09;基本结构&#xff1a;PN结导电沟道 &#xff08;2&#xff09;工作原理&#xff1a;耗尽区挤压沟道从而控制电流 &#xff08;3&#xff09;特性曲线 1.转移特性 2.输出特性 …

开发安全利器:detect-secrets 敏感信息扫描工具实战指南

在现代软件开发流程中&#xff0c;代码安全已成为不可忽视的重要环节。尤其是在 DevSecOps 的理念逐渐普及的今天&#xff0c;如何在开发早期就发现并消除潜在的安全隐患&#xff0c;成为每一个开发者和安全工程师必须面对的问题。其中&#xff0c;敏感信息泄露&#xff08;Sec…

数字经济专业核心课程解析与职业发展指南

在数字经济高速发展的时代&#xff0c;选择一门与未来趋势紧密关联的专业至关重要。数字经济专业作为新兴交叉学科&#xff0c;既涵盖传统经济理论&#xff0c;又融合了大数据、人工智能等前沿技术。想要在这一领域脱颖而出&#xff0c;考取权威证书是提升竞争力的有效途径。其…

使用yolo11训练航拍图片微小目标AI-TOD检测数据集无损压缩版YOLO格式14018张8类别已划分好训练验证集步骤和流程

【数据集介绍】我们基于公开的大规模航空图像数据集构建了AI-TOD&#xff0c;这些数据集包括&#xff1a;DOTA-v1.5的训练验证集[1]、xView的训练集[19]、VisDrone2018-Det的训练验证集[20]、Airbus Ship的训练验证集1以及DIOR的训练验证测试集[3]。这些数据集的详细信息如下&a…

sward V2.0.6版本发布,支持OnlyOffice集成、文档权限控制及归档等功能

1、版本更新日志新增新增目录文档权限控制新增新增知识库、文档归档功能集成OnlyOffice支持word文档预览、编辑新增MarkDown代码块根据语言展示不同样式优化优化富文本在小屏幕操作调整优化部分界面展示效果优化知识库图片展示效果2、目录与文档权限控制默认情况下&#xff0c;…

多因子AI回归揭示通胀-就业背离,黄金价格稳态区间的时序建模

摘要&#xff1a;本文通过构建包含通胀韧性、就业疲软、货币政策预期及跨市场联动的多因子量化模型&#xff0c;结合美国8月CPI超预期上行与初请失业金人数激增的动态数据&#xff0c;分析黄金价格的高位持稳机制&#xff0c;揭示就业市场对美联储降息预期的协同支撑效应。一、…

Java--多线程基础知识(2)

一.多线程的中断1.通过自定义的变量来作为标志位import java.util.Scanner;public class Demo1 {public static boolean flg false;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(()->{while (!flg){System.out.println(&qu…