django連接minio實現文件上傳下載(提供接口示例)

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…