List of mine types

本文列举了各种文件扩展名及其对应的MIME类型,包括常见的文档、图像、音频、视频等格式。有助于开发者正确设置HTTP响应头,确保文件在网络上传输时被正确解析。

List of mine types

 

".*"="application/octet-stream"
".001"="application/x-001"
".301"="application/x-301"
".323"="text/h323"
".906"="application/x-906"
".907"="drawing/907"
".a11"="application/x-a11"
".acp"="audio/x-mei-aac"
".ai"="application/postscript"
".aif"="audio/aiff"
".aifc"="audio/aiff"
".aiff"="audio/aiff"
".anv"="application/x-anv"
".asa"="text/asa"
".asf"="video/x-ms-asf"
".asp"="text/asp"
".asx"="video/x-ms-asf"
".au"="audio/basic"
".avi"="video/avi"
".awf"="application/vnd.adobe.workflow"
".biz"="text/xml"
".bmp"="application/x-bmp"
".bot"="application/x-bot"
".c4t"="application/x-c4t"
".c90"="application/x-c90"
".cal"="application/x-cals"
".cat"="application/vnd.ms-pki.seccat"
".cdf"="application/x-netcdf"
".cdr"="application/x-cdr"
".cel"="application/x-cel"
".cer"="application/x-x509-ca-cert"
".cg4"="application/x-g4"
".cgm"="application/x-cgm"
".cit"="application/x-cit"
".class"="java/*"
".cml"="text/xml"
".cmp"="application/x-cmp"
".cmx"="application/x-cmx"
".cot"="application/x-cot"
".crl"="application/pkix-crl"
".crt"="application/x-x509-ca-cert"
".csi"="application/x-csi"
".css"="text/css"
".cut"="application/x-cut"
".dbf"="application/x-dbf"
".dbm"="application/x-dbm"
".dbx"="application/x-dbx"
".dcd"="text/xml"
".dcx"="application/x-dcx"
".der"="application/x-x509-ca-cert"
".dgn"="application/x-dgn"
".dib"="application/x-dib"
".dll"="application/x-msdownload"
".doc"="application/msword"
".dot"="application/msword"
".drw"="application/x-drw"
".dtd"="text/xml"
".dwf"="Model/vnd.dwf"
".dwf"="application/x-dwf"
".dwg"="application/x-dwg"
".dxb"="application/x-dxb"
".dxf"="application/x-dxf"
".edn"="application/vnd.adobe.edn"
".emf"="application/x-emf"
".eml"="message/rfc822"
".ent"="text/xml"
".epi"="application/x-epi"
".eps"="application/x-ps"
".eps"="application/postscript"
".etd"="application/x-ebx"
".exe"="application/x-msdownload"
".fax"="image/fax"
".fdf"="application/vnd.fdf"
".fif"="application/fractals"
".fo"="text/xml"
".frm"="application/x-frm"
".g4"="application/x-g4"
".gbr"="application/x-gbr"
".gcd"="application/x-gcd"
".gif"="image/gif"
".gl2"="application/x-gl2"
".gp4"="application/x-gp4"
".hgl"="application/x-hgl"
".hmr"="application/x-hmr"
".hpg"="application/x-hpgl"
".hpl"="application/x-hpl"
".hqx"="application/mac-binhex40"
".hrf"="application/x-hrf"
".hta"="application/hta"
".htc"="text/x-component"
".htm"="text/html"
".html"="text/html"
".htt"="text/webviewhtml"
".htx"="text/html"
".icb"="application/x-icb"
".ico"="image/x-icon"
".ico"="application/x-ico"
".iff"="application/x-iff"
".ig4"="application/x-g4"
".igs"="application/x-igs"
".iii"="application/x-iphone"
".img"="application/x-img"
".ins"="application/x-internet-signup"
".isp"="application/x-internet-signup"
".IVF"="video/x-ivf"
".java"="java/*"
".jfif"="image/jpeg"
".jpe"="image/jpeg"
".jpe"="application/x-jpe"
".jpeg"="image/jpeg"
".jpg"="image/jpeg"
".jpg"="application/x-jpg"
".js"="application/x-javascript"
".jsp"="text/html"
".la1"="audio/x-liquid-file"
".lar"="application/x-laplayer-reg"
".latex"="application/x-latex"
".lavs"="audio/x-liquid-secure"
".lbm"="application/x-lbm"
".lmsff"="audio/x-la-lms"
".ls"="application/x-javascript"
".ltr"="application/x-ltr"
".m1v"="video/x-mpeg"
".m2v"="video/x-mpeg"
".m3u"="audio/mpegurl"
".m4e"="video/mpeg4"
".mac"="application/x-mac"
".man"="application/x-troff-man"
".math"="text/xml"
".mdb"="application/msaccess"
".mdb"="application/x-mdb"
".mfp"="application/x-shockwave-flash"
".mht"="message/rfc822"
".mhtml"="message/rfc822"
".mi"="application/x-mi"
".mid"="audio/mid"
".midi"="audio/mid"
".mil"="application/x-mil"
".mml"="text/xml"
".mnd"="audio/x-musicnet-download"
".mns"="audio/x-musicnet-stream"
".mocha"="application/x-javascript"
".movie"="video/x-sgi-movie"
".mp1"="audio/mp1"
".mp2"="audio/mp2"
".mp2v"="video/mpeg"
".mp3"="audio/mp3"
".mp4"="video/mpeg4"
".mpa"="video/x-mpg"
".mpd"="application/vnd.ms-project"
".mpe"="video/x-mpeg"
".mpeg"="video/mpg"
".mpg"="video/mpg"
".mpga"="audio/rn-mpeg"
".mpp"="application/vnd.ms-project"
".mps"="video/x-mpeg"
".mpt"="application/vnd.ms-project"
".mpv"="video/mpg"
".mpv2"="video/mpeg"
".mpw"="application/vnd.ms-project"
".mpx"="application/vnd.ms-project"
".mtx"="text/xml"
".mxp"="application/x-mmxp"
".net"="image/pnetvue"
".nrf"="application/x-nrf"
".nws"="message/rfc822"
".odc"="text/x-ms-odc"
".out"="application/x-out"
".p10"="application/pkcs10"
".p12"="application/x-pkcs12"
".p7b"="application/x-pkcs7-certificates"
".p7c"="application/pkcs7-mime"
".p7m"="application/pkcs7-mime"
".p7r"="application/x-pkcs7-certreqresp"
".p7s"="application/pkcs7-signature"
".pc5"="application/x-pc5"
".pci"="application/x-pci"
".pcl"="application/x-pcl"
".pcx"="application/x-pcx"
".pdf"="application/pdf"
".pdf"="application/pdf"
".pdx"="application/vnd.adobe.pdx"
".pfx"="application/x-pkcs12"
".pgl"="application/x-pgl"
".pic"="application/x-pic"
".pko"="application/vnd.ms-pki.pko"
".pl"="application/x-perl"
".plg"="text/html"
".pls"="audio/scpls"
".plt"="application/x-plt"
".png"="image/png"
".png"="application/x-png"
".pot"="application/vnd.ms-powerpoint"
".ppa"="application/vnd.ms-powerpoint"
".ppm"="application/x-ppm"
".pps"="application/vnd.ms-powerpoint"
".ppt"="application/vnd.ms-powerpoint"
".ppt"="application/x-ppt"
".pr"="application/x-pr"
".prf"="application/pics-rules"
".prn"="application/x-prn"
".prt"="application/x-prt"
".ps"="application/x-ps"
".ps"="application/postscript"
".ptn"="application/x-ptn"
".pwz"="application/vnd.ms-powerpoint"
".r3t"="text/vnd.rn-realtext3d"
".ra"="audio/vnd.rn-realaudio"
".ram"="audio/x-pn-realaudio"
".ras"="application/x-ras"
".rat"="application/rat-file"
".rdf"="text/xml"
".rec"="application/vnd.rn-recording"
".red"="application/x-red"
".rgb"="application/x-rgb"
".rjs"="application/vnd.rn-realsystem-rjs"
".rjt"="application/vnd.rn-realsystem-rjt"
".rlc"="application/x-rlc"
".rle"="application/x-rle"
".rm"="application/vnd.rn-realmedia"
".rmf"="application/vnd.adobe.rmf"
".rmi"="audio/mid"
".rmj"="application/vnd.rn-realsystem-rmj"
".rmm"="audio/x-pn-realaudio"
".rmp"="application/vnd.rn-rn_music_package"
".rms"="application/vnd.rn-realmedia-secure"
".rmvb"="application/vnd.rn-realmedia-vbr"
".rmx"="application/vnd.rn-realsystem-rmx"
".rnx"="application/vnd.rn-realplayer"
".rp"="image/vnd.rn-realpix"
".rpm"="audio/x-pn-realaudio-plugin"
".rsml"="application/vnd.rn-rsml"
".rt"="text/vnd.rn-realtext"
".rtf"="application/msword"
".rtf"="application/x-rtf"
".rv"="video/vnd.rn-realvideo"
".sam"="application/x-sam"
".sat"="application/x-sat"
".sdp"="application/sdp"
".sdw"="application/x-sdw"
".sit"="application/x-stuffit"
".slb"="application/x-slb"
".sld"="application/x-sld"
".slk"="drawing/x-slk"
".smi"="application/smil"
".smil"="application/smil"
".smk"="application/x-smk"
".snd"="audio/basic"
".sol"="text/plain"
".sor"="text/plain"
".spc"="application/x-pkcs7-certificates"
".spl"="application/futuresplash"
".spp"="text/xml"
".ssm"="application/streamingmedia"
".sst"="application/vnd.ms-pki.certstore"
".stl"="application/vnd.ms-pki.stl"
".stm"="text/html"
".sty"="application/x-sty"
".svg"="text/xml"
".swf"="application/x-shockwave-flash"
".tdf"="application/x-tdf"
".tg4"="application/x-tg4"
".tga"="application/x-tga"
".tif"="image/tiff"
".tif"="application/x-tif"
".tiff"="image/tiff"
".tld"="text/xml"
".top"="drawing/x-top"
".torrent"="application/x-bittorrent"
".tsd"="text/xml"
".txt"="text/plain"
".uin"="application/x-icq"
".uls"="text/iuls"
".vcf"="text/x-vcard"
".vda"="application/x-vda"
".vdx"="application/vnd.visio"
".vml"="text/xml"
".vpg"="application/x-vpeg005"
".vsd"="application/vnd.visio"
".vsd"="application/x-vsd"
".vss"="application/vnd.visio"
".vst"="application/vnd.visio"
".vst"="application/x-vst"
".vsw"="application/vnd.visio"
".vsx"="application/vnd.visio"
".vtx"="application/vnd.visio"
".vxml"="text/xml"
".wav"="audio/wav"
".wax"="audio/x-ms-wax"
".wb1"="application/x-wb1"
".wb2"="application/x-wb2"
".wb3"="application/x-wb3"
".wbmp"="image/vnd.wap.wbmp"
".wiz"="application/msword"
".wk3"="application/x-wk3"
".wk4"="application/x-wk4"
".wkq"="application/x-wkq"
".wks"="application/x-wks"
".wm"="video/x-ms-wm"
".wma"="audio/x-ms-wma"
".wmd"="application/x-ms-wmd"
".wmf"="application/x-wmf"
".wml"="text/vnd.wap.wml"
".wmv"="video/x-ms-wmv"
".wmx"="video/x-ms-wmx"
".wmz"="application/x-ms-wmz"
".wp6"="application/x-wp6"
".wpd"="application/x-wpd"
".wpg"="application/x-wpg"
".wpl"="application/vnd.ms-wpl"
".wq1"="application/x-wq1"
".wr1"="application/x-wr1"
".wri"="application/x-wri"
".wrk"="application/x-wrk"
".ws"="application/x-ws"
".ws2"="application/x-ws"
".wsc"="text/scriptlet"
".wsdl"="text/xml"
".wvx"="video/x-ms-wvx"
".xdp"="application/vnd.adobe.xdp"
".xdr"="text/xml"
".xfd"="application/vnd.adobe.xfd"
".xfdf"="application/vnd.adobe.xfdf"
".xhtml"="text/html"
".xls"="application/vnd.ms-excel"
".xls"="application/x-xls"
".xlw"="application/x-xlw"
".xml"="text/xml"
".xpl"="audio/scpls"
".xq"="text/xml"
".xql"="text/xml"
".xquery"="text/xml"
".xsd"="text/xml"
".xsl"="text/xml"
".xslt"="text/xml"
".xwd"="application/x-xwd"
".x_b"="application/x-x_b"
".x_t"="application/x-x_t"

 

 

 

 

'ez'         => 'application/andrew-inset',

     'hqx'         => 'application/mac-binhex40',

     'cpt'         => 'application/mac-compactpro',

     'doc'         => 'application/msword',

     'bin'         => 'application/octet-stream',

     'dms'         => 'application/octet-stream',

     'lha'         => 'application/octet-stream',

     'lzh'         => 'application/octet-stream',

     'exe'         => 'application/octet-stream',

     'class'         => 'application/octet-stream',

     'so'         => 'application/octet-stream',

     'dll'         => 'application/octet-stream',

     'oda'         => 'application/oda',

     'pdf'         => 'application/pdf',

     'ai'         => 'application/postscript',

     'eps'         => 'application/postscript',

     'ps'         => 'application/postscript',

     'smi'         => 'application/smil',

     'smil'         => 'application/smil',

     'mif'         => 'application/vnd.mif',

     'xls'         => 'application/vnd.ms-excel',

     'ppt'         => 'application/vnd.ms-powerpoint',

     'wbxml'         => 'application/vnd.wap.wbxml',

     'wmlc'         => 'application/vnd.wap.wmlc',

     'wmlsc'         => 'application/vnd.wap.wmlscriptc',

     'bcpio'         => 'application/x-bcpio',

     'vcd'         => 'application/x-cdlink',

     'pgn'         => 'application/x-chess-pgn',

     'cpio'         => 'application/x-cpio',

     'csh'         => 'application/x-csh',

     'dcr'         => 'application/x-director',

     'dir'         => 'application/x-director',

     'dxr'         => 'application/x-director',

     'dvi'         => 'application/x-dvi',

     'spl'         => 'application/x-futuresplash',

     'gtar'         => 'application/x-gtar',

     'hdf'         => 'application/x-hdf',

     'js'         => 'application/x-javascript',

     'skp'         => 'application/x-koan',

     'skd'         => 'application/x-koan',

     'skt'         => 'application/x-koan',

     'skm'         => 'application/x-koan',

     'latex'         => 'application/x-latex',

     'nc'         => 'application/x-netcdf',

     'cdf'         => 'application/x-netcdf',

     'sh'         => 'application/x-sh',

     'shar'         => 'application/x-shar',

     'swf'         => 'application/x-shockwave-flash',

     'sit'         => 'application/x-stuffit',

     'sv4cpio'     => 'application/x-sv4cpio',

     'sv4crc'     => 'application/x-sv4crc',

     'tar'         => 'application/x-tar',

     'tcl'         => 'application/x-tcl',

     'tex'         => 'application/x-tex',

     'texinfo'     => 'application/x-texinfo',

     'texi'         => 'application/x-texinfo',

     't'             => 'application/x-troff',

     'tr'         => 'application/x-troff',

     'roff'         => 'application/x-troff',

     'man'         => 'application/x-troff-man',

     'me'         => 'application/x-troff-me',

     'ms'         => 'application/x-troff-ms',

     'ustar'         => 'application/x-ustar',

     'src'         => 'application/x-wais-source',

     'xhtml'         => 'application/xhtml+xml',

     'xht'         => 'application/xhtml+xml',

     'zip'         => 'application/zip',

     'au'         => 'audio/basic',

     'snd'         => 'audio/basic',

     'mid'         => 'audio/midi',

     'midi'         => 'audio/midi',

     'kar'         => 'audio/midi',

     'mpga'         => 'audio/mpeg',

     'mp2'         => 'audio/mpeg',

     'mp3'         => 'audio/mpeg',

     'aif'         => 'audio/x-aiff',

     'aiff'         => 'audio/x-aiff',

     'aifc'         => 'audio/x-aiff',

     'm3u'         => 'audio/x-mpegurl',

     'ram'         => 'audio/x-pn-realaudio',

     'rm'         => 'audio/x-pn-realaudio',

     'rpm'         => 'audio/x-pn-realaudio-plugin',

     'ra'         => 'audio/x-realaudio',

     'wav'         => 'audio/x-wav',

     'pdb'         => 'chemical/x-pdb',

     'xyz'         => 'chemical/x-xyz',

     'bmp'         => 'image/bmp',

     'gif'         => 'image/gif',

     'ief'         => 'image/ief',

     'jpeg'         => 'image/jpeg',

     'jpg'         => 'image/jpeg',

     'jpe'         => 'image/jpeg',

     'png'         => 'image/png',

     'tiff'         => 'image/tiff',

     'tif'         => 'image/tiff',

     'djvu'         => 'image/vnd.djvu',

     'djv'         => 'image/vnd.djvu',

     'wbmp'         => 'image/vnd.wap.wbmp',

     'ras'         => 'image/x-cmu-raster',

     'pnm'         => 'image/x-portable-anymap',

     'pbm'         => 'image/x-portable-bitmap',

     'pgm'         => 'image/x-portable-graymap',

     'ppm'         => 'image/x-portable-pixmap',

     'rgb'         => 'image/x-rgb',

     'xbm'         => 'image/x-xbitmap',

     'xpm'         => 'image/x-xpixmap',

     'xwd'         => 'image/x-xwindowdump',

     'igs'         => 'model/iges',

     'iges'         => 'model/iges',

     'msh'         => 'model/mesh',

     'mesh'         => 'model/mesh',

     'silo'         => 'model/mesh',

     'wrl'         => 'model/vrml',

     'vrml'         => 'model/vrml',

     'css'         => 'text/css',

     'html'         => 'text/html',

     'htm'         => 'text/html',

     'asc'         => 'text/plain',

     'txt'         => 'text/plain',

     'rtx'         => 'text/richtext',

     'rtf'         => 'text/rtf',

     'sgml'         => 'text/sgml',

     'sgm'         => 'text/sgml',

     'tsv'         => 'text/tab-separated-values',

     'wml'         => 'text/vnd.wap.wml',

     'wmls'         => 'text/vnd.wap.wmlscript',

     'etx'         => 'text/x-setext',

     'xsl'         => 'text/xml',

     'xml'         => 'text/xml',

     'mpeg'         => 'video/mpeg',

     'mpg'         => 'video/mpeg',

     'mpe'         => 'video/mpeg',

     'qt'         => 'video/quicktime',

     'mov'         => 'video/quicktime',

     'mxu'         => 'video/vnd.mpegurl',

     'avi'         => 'video/x-msvideo',

     'movie'         => 'video/x-sgi-movie',

     'ice'         => 'x-conference/x-cooltalk


application/andrew-insetez
application/mac-binhex40hqx
application/mac-compactprocpt
application/mathml+xmlmathml
application/msworddoc
application/octet-streambin dms lha lzh exe class so dll
application/odaoda
application/oggogg
application/pdfpdf
application/postscriptai eps ps
application/rdf+xmlrdf
application/smilsmi smil
application/srgsgram
application/srgs+xmlgrxml
application/vnd.mifmif
application/vnd.mozilla.xul+xmlxul
application/vnd.ms-excelxls
application/vnd.ms-powerpointppt
application/vnd.wap.wbxmlwbxml
application/vnd.wap.wmlc.wmlc wmlc
application/vnd.wap.wmlscriptc.wmlsc wmlsc
application/voicexml+xmlvxml
application/x-bcpiobcpio
application/x-cdlinkvcd
application/x-chess-pgnpgn
application/x-cpiocpio
application/x-cshcsh
application/x-directordcr dir dxr
application/x-dvidvi
application/x-futuresplashspl
application/x-gtargtar
application/x-hdfhdf
application/x-httpd-php.php .php4 .php3 .phtml
application/x-httpd-php-source.phps
application/x-javascriptjs
application/x-koanskp skd skt skm
application/x-latexlatex
application/x-netcdfnc cdf
application/x-pkcs7-crl.crl
application/x-shsh
application/x-sharshar
application/x-shockwave-flashswf
application/x-stuffitsit
application/x-sv4cpiosv4cpio
application/x-sv4crcsv4crc
application/x-tar.tgz tar
application/x-tcltcl
application/x-textex
application/x-texinfotexinfo texi
application/x-trofft tr roff
application/x-troff-manman
application/x-troff-meme
application/x-troff-msms
application/x-ustarustar
application/x-wais-sourcesrc
application/x-x509-ca-cert.crt
application/xhtml+xmlxhtml xht
application/xmlxml xsl
application/xml-dtddtd
application/xslt+xmlxslt
application/zipzip
audio/basicau snd
audio/midimid midi kar
audio/mpegmpga mp2 mp3
audio/x-aiffaif aiff aifc
audio/x-mpegurlm3u
audio/x-pn-realaudioram rm
audio/x-pn-realaudio-pluginrpm
audio/x-realaudiora
audio/x-wavwav
chemical/x-pdbpdb
chemical/x-xyzxyz
image/bmpbmp
image/cgmcgm
image/gifgif
image/iefief
image/jpegjpeg jpg jpe
image/pngpng
image/svg+xmlsvg
image/tifftiff tif
image/vnd.djvudjvu djv
image/vnd.wap.wbmp.wbmp wbmp
image/x-cmu-rasterras
image/x-iconico
image/x-portable-anymappnm
image/x-portable-bitmappbm
image/x-portable-graymappgm
image/x-portable-pixmapppm
image/x-rgbrgb
image/x-xbitmapxbm
image/x-xpixmapxpm
image/x-xwindowdumpxwd
model/igesigs iges
model/meshmsh mesh silo
model/vrmlwrl vrml
text/calendarics ifb
text/csscss
text/html.shtml html htm
text/plainasc txt
text/richtextrtx
text/rtfrtf
text/sgmlsgml sgm
text/tab-separated-valuestsv
text/vnd.wap.wml.wml wml
text/vnd.wap.wmlscript.wmls wmls
text/x-setextetx
video/mpegmpeg mpg mpe
video/quicktimeqt mov
video/vnd.mpegurlmxu
video/x-msvideoavi
video/x-sgi-moviemovie
x-conference/x-cooltalk

ice

 

 

from abc import abstractmethod import asyncio from contextlib import AsyncExitStack import os import shutil import traceback from pydantic import Field from typing import Any, Optional, Dict, List from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from mcp.client.sse import sse_client from mcp.client.streamable_http import streamablehttp_client from mine_agenix.core.logger import logger from mine_agenix.models.base import ToolResponse from mine_agenix.models.mcp import ConnectTypeEnum, McpServe, MCPTool,MCPResource,MCPPrompt from mine_agenix.services.error import MCPConnectError, MCPInitialError,MCPParamError, MCPNoInitialError,MCPAlreadyInitialError,MCPRequestError,ToolCallError from mine_agenix.services.mcp.mcp_connect_base import MCPConnectBase from datetime import timedelta class MCPServerConnect(MCPConnectBase): stdio_context: Any | None = None session: ClientSession | None = None _cleanup_lock: asyncio.Lock = asyncio.Lock() exit_stack: AsyncExitStack = AsyncExitStack() tools: List[MCPTool] = [] resources: List[MCPResource] = [] prompts: List[MCPPrompt] = [] model_config = { "arbitrary_types_allowed": True } def __id__(self): return self.id def is_connected(self): return self.session is not None @abstractmethod async def initialize(self, ignore_if_inited:bool=True)->None: """ 初始化连接 """ pass async def list_tools(self) -> list[MCPTool]: """List available tools from the server. Returns: A list of available tools. Raises: RuntimeError: If the server is not initialized. """ if not self.session: raise MCPNoInitialError(f"Server {self.name} not initialized") # if self.tools and len(self.tools)>1: # return self.tools try: tools_response = await self.session.list_tools() except Exception as e: logger.info("failed get tools from server %s.", self.name) try: await self.reconnect() tools_response = await self.session.list_tools() except: raise MCPRequestError("Mcp server request failed, %s mabye not running", self.name) tools = [] for item in tools_response: if isinstance(item, tuple) and item[0] == "tools": tools.extend( [MCPTool(name=tool.name, description=tool.description, parameters=tool.inputSchema, connect_name=self.name) for tool in item[1]] ) self.tools = tools return tools async def list_resources(self) -> list[MCPResource]: """List available resources from the server. Returns: A list of available resources. Raises: RuntimeError: If the server is not initialized. """ if not self.session: raise MCPNoInitialError(f"Server {self.name} not initialized") try: resources_response = await self.session.list_resources() except: logger.info("failed get resources from server %s.", self.name) try: await self.reconnect() resources_response = await self.session.list_resources() except: raise MCPRequestError("Mcp server request failed, %s mabye not running", self.name) resources: List[MCPResource] = [] for item in resources_response.resources: mcp_resource = MCPResource( name=item.name, uri=item.uri, description=item.description ) resources.append(mcp_resource) # 使用 append 替代 extend #resources.extend([MCPResource(name=self.id+item.name, uri=item.uri,description=item.description)]) self.resources = resources return resources async def list_prompts(self) -> list[MCPPrompt]: """List available prompts from the server. Returns: A list of available prompts. Raises: RuntimeError: If the server is not initialized. """ if not self.session: raise MCPNoInitialError(f"Server {self.name} not initialized") try: prompts_response = await self.session.list_prompts() except: logger.info("failed get prompts from server %s.", self.name) try: await self.reconnect() prompts_response = await self.session.list_prompts() except: raise MCPRequestError("Mcp server request failed, %s mabye not running", self.name) prompts: List[MCPPrompt] = [] for item in prompts_response.prompts: mcp_prompts = MCPPrompt( name=item.name, description=item.description or "", arguments=item.arguments ) prompts.append(mcp_prompts) # 使用 append 替代 extend #prompts.extend([MCPPrompt(name=self.id+item.name, description=item.description, arguments=item.arguments)]) self.prompts = prompts return prompts async def execute_tool( self, tool_name: str, arguments: dict[str, Any], retries: int = 2, delay: float = 1.0, ) -> ToolResponse | None: """Execute a tool with retry mechanism. Args: tool_name: Name of the tool to execute. arguments: Tool arguments. retries: Number of retry attempts. delay: Delay between retries in seconds. Returns: Tool execution result. Raises: RuntimeError: If server is not initialized. Exception: If tool execution fails after all retries. """ if not self.session: raise MCPNoInitialError(f"Server {self.name} not initialized") tool = await self.get_tool_by_unique_name(tool_name) if tool is None: raise ToolCallError(f"Tool {tool_name} not found") attempt = 0 while attempt < retries: try: logger.debug(f"Executing {tool.name}...") result = await self.session.call_tool(tool.name, arguments) return ToolResponse.from_call_tool_result(result) except Exception as e: logger.error(f"Error executing tool: {traceback.format_exc()}") attempt += 1 logger.debug( f"Error executing tool: {e}. Attempt {attempt} of {retries}." ) if attempt < retries: logger.debug(f"Retrying in {delay} seconds...") await asyncio.sleep(delay) await self.reconnect() else: logger.debug("Max retries reached. Failing.") raise MCPRequestError(f"Tool {tool.name} failed after {retries} retries.") async def cleanup(self) -> None: """Clean up server resources.""" if self.session is None: return async with self._cleanup_lock: try: await self.exit_stack.aclose() except Exception as e: logger.error(f"Error during cleanup of server {self.name}: {e}") finally: self.session = None self.stdio_context = None async def reconnect(self) -> None: """Reconnect to the server.""" logger.warning("Reconnecting to mcp server %s...", self.name) await self.cleanup() attempts = 0 max_attempts = 2 while attempts < max_attempts: try: await self.initialize(False) await asyncio.sleep(0.3) return except Exception as e: logger.warning("Failed to reconnect to mcp server %s because: %s, retrying...", self.name, str(e)) await asyncio.sleep(0.3) finally: attempts += 1 raise MCPConnectError("Failed to reconnect to mcp server %s", self.name) @staticmethod def from_mcpserve(s: McpServe) -> MCPConnectBase: if s.connect_type == ConnectTypeEnum.SSE: tmp_headers = {e.split("=")[0].strip(): e.split("=")[1].strip() for e in s.headers.split(",")} if s.headers else None if s.url is None: raise MCPParamError("The url must be a valid string and cannot be None.") return MCPSseServerConnect(id=s.id, name=s.name, url=s.url, headers=tmp_headers) elif s.connect_type == ConnectTypeEnum.STREAM: tmp_headers = {e.split("=")[0].strip(): e.split("=")[1].strip() for e in s.headers.split(",")} if s.headers else None if s.url is None: raise MCPParamError("The url must be a valid string and cannot be None.") return MCPStreamServerConnect(id=s.id, name=s.name, url=s.url, headers=tmp_headers) else: if s.command is None: raise MCPParamError("The command must be a valid string and cannot be None.") command_args= [a.strip() for a in s.arguments.split(" ")] if s.arguments else [] tmp_envs = {e.split("=")[0].strip(): e.split("=")[1].strip() for e in s.envs.split(",") if "=" in e} if s.envs else {} return MCPStdioServerConnect(id=s.id, name=s.name,command=s.command, args=command_args, envs=tmp_envs) class MCPStdioServerConnect(MCPServerConnect): """Manages MCP server connections and tool execution.""" command: str args: List[str]=[] envs: dict[str, str] = Field(default_factory=dict, description="stdio连接 环境变量") async def initialize(self,ignore_if_inited:bool=True) -> None: """Initialize the server connection.""" if self.session: if ignore_if_inited: return raise MCPAlreadyInitialError() command = ( shutil.which("npx") if self.command == "npx" else self.command ) if command is None: raise MCPParamError("The command must be a valid string and cannot be None.") server_params = StdioServerParameters( command=command, args=self.args, env={**os.environ, **self.envs} if self.envs else None, ) try: stdio_transport = await self.exit_stack.enter_async_context( stdio_client(server_params) ) read, write = stdio_transport session = await self.exit_stack.enter_async_context( ClientSession(read, write) ) await session.initialize() self.session = session except Exception as e: logger.error(f"Error initializing server {self.name}: {e}") await self.cleanup() raise MCPConnectError() class MCPSseServerConnect(MCPServerConnect): """Manages MCP server connections and tool execution.""" url:str headers: Optional[dict[str,str]]=Field(default_factory=dict, description="sse连接 头部") async def initialize(self, ignore_if_inited:bool=True) -> None: """Initialize the server connection.""" if self.session: if ignore_if_inited: return raise MCPAlreadyInitialError() try: stdio_transport = await self.exit_stack.enter_async_context( sse_client(self.url, self.headers) ) read, write = stdio_transport session = await self.exit_stack.enter_async_context( ClientSession(read, write) ) self.session = session await session.initialize() except Exception as e: logger.error(f"Error initializing server {self.name}: {e}") await self.cleanup() raise MCPInitialError() class MCPStreamServerConnect(MCPServerConnect): """Manages MCP server streamable HTTP connections.""" url: str headers: Optional[Dict[str, str]] = Field(default_factory=dict, description="流式HTTP连接头部信息") async def initialize(self, ignore_if_inited:bool=True) -> None: """Initialize the server connection.""" if self.session: if ignore_if_inited: return raise MCPAlreadyInitialError() try: async with asyncio.timeout(10): stdio_transport = await self.exit_stack.enter_async_context( streamablehttp_client(self.url, self.headers) ) read, write , _ = stdio_transport session = await self.exit_stack.enter_async_context( ClientSession(read, write) ) self.session = session async with asyncio.timeout(15): await session.initialize() # 捕获连接超时 except asyncio.TimeoutError: logger.error(f"连接 {self.url} 超时(建立连接或初始化未响应)") await self.cleanup() raise MCPInitialError("连接超时,服务器未响应") # 捕获任务取消(关键!之前未处理) except asyncio.CancelledError: logger.error(f"连接 {self.url} 被中断(可能因超时或网络问题)") await self.cleanup() raise MCPInitialError("连接被中断,请检查服务器状态") except Exception as e: logger.error(f"Error initializing server {self.name}: {e}") await self.cleanup() raise MCPInitialError() streamable-http Error during cleanup of server 测试stream: Attempted to exit cancel scope in a different task than it was entered in报错
最新发布
10-24
检查,尤其是参数值传递过程import numpy as np import pandas as pd from tabulate import tabulate import random import math from collections import deque, defaultdict import heapq import networkx as nx from concurrent.futures import ThreadPoolExecutor, as_completed import matplotlib.pyplot as plt from matplotlib.patches import Patch from tqdm import tqdm import time import itertools # 配置参数 max_weight = 1200 # kg initial_money = 10000 # 元 # 资源参数 per_water_weight = 3 # kg/箱 water_price = 5 # 元/箱 water_sunny = 3 # 箱/天 water_hot = 9 water_sandstorm = 10 per_food_weight = 2 # kg/箱 food_price = 10 # 元/箱 food_sunny = 4 food_hot = 9 food_sandstorm = 10 # 天气类型和消耗量 WEATHER_TYPES = ['晴朗', '高温', '沙暴'] WEATHER_PROBS = [0.3, 0.5, 0.2] WEATHER_CONSUMPTION = { '晴朗': {'water': water_sunny, 'food': food_sunny}, '高温': {'water': water_hot, 'food': food_hot}, '沙暴': {'water': water_sandstorm, 'food': food_sandstorm} } # 地图参数 rows = 5 # 行数 cols = 5 # 列数 total_regions = rows * cols # 总区域数 # 创建邻接矩阵 adj_matrix = [[0 for _ in range(total_regions + 1)] for _ in range(total_regions + 1)] # 创建连接关系 for region in range(1, total_regions + 1): # 计算当前区域的行和列 row = (region - 1) // cols + 1 col = (region - 1) % cols + 1 # 检查上方邻居 if row > 1: neighbor = region - cols adj_matrix[region][neighbor] = 1 adj_matrix[neighbor][region] = 1 # 检查下方邻居 if row < rows: neighbor = region + cols adj_matrix[region][neighbor] = 1 adj_matrix[neighbor][region] = 1 # 检查左侧邻居 if col > 1: neighbor = region - 1 adj_matrix[region][neighbor] = 1 adj_matrix[neighbor][region] = 1 # 检查右侧邻居 if col < cols: neighbor = region + 1 adj_matrix[region][neighbor] = 1 adj_matrix[neighbor][region] = 1 # 节点类型定义 NODE_TYPES = { 'NORMAL': 0, 'START': 1, # 起点 'MINE': 2, # 矿山 'VILLAGE': 3, # 村庄 'END': 4 # 终点 } # 节点类型初始化 node_types = [NODE_TYPES['NORMAL']] * (total_regions + 1) # 设置特殊节点 node_types[1] = NODE_TYPES['START'] node_types[18] = NODE_TYPES['MINE'] node_types[14] = NODE_TYPES['VILLAGE'] node_types[25] = NODE_TYPES['END'] # 场景生成参数 SCENARIO_COUNT = 50 # 场景数量 MAX_DAYS = 30 # 最大天数 def get_node_type_name(node_type): """根据节点类型值获取名称""" for name, value in NODE_TYPES.items(): if value == node_type: return name return "UNKNOWN" # 创建NetworkX图 G = nx.Graph() def generate_weather_scenarios(days, count): """生成指定天数和数量的天气场景""" scenarios = [] for _ in range(count): scenario = random.choices(WEATHER_TYPES, weights=WEATHER_PROBS, k=days) scenarios.append(scenario) return scenarios # 使用全局缓存加速最短路径计算 def init_shortest_path_cache(): """初始化最短路径缓存""" shortest_path_cache = {} for u in range(1, total_regions + 1): for v in range(1, total_regions + 1): if u != v: try: shortest_path_cache[(u, v)] = nx.shortest_path_length(G, u, v) except nx.NetworkXNoPath: shortest_path_cache[(u, v)] = float('inf') return shortest_path_cache # 初始化全局最短路径缓存 shortest_path_cache = init_shortest_path_cache() def heuristic(current, end, remaining_days, money): """启发函数,使用全局缓存""" # 如果无法到达终点,只考虑当前金钱 if shortest_path_cache[(current, end)] == float('inf'): return money # 否则,考虑剩余天数和可能的采矿收益 potential_mines = max(0, remaining_days - shortest_path_cache[(current, end)]) // 2 return money + potential_mines * 1000 def solve_deterministic_model(G, weather_sequence, start=1, end=25, best_money_cache=None): """优化的A*算法""" # 如果有全局缓存,使用它 if best_money_cache is not None and (start, end) in best_money_cache: best_result, best_money = best_money_cache[(start, end)] if best_money > 0: return best_result # 使用优先队列实现A*算法 queue = [] visited = set() # 初始购买策略(在起点购买资源) max_water = min(max_weight // per_water_weight, initial_money // water_price) max_food = min(max_weight // per_food_weight, initial_money // food_price) # 使用更大数据步长 water_steps = list(range(0, max_water + 1, 40)) food_steps = list(range(0, max_food + 1, 40)) # 批量处理初始状态 states = [] for water, food in itertools.product(water_steps, food_steps): cost = water * water_price + food * food_price if cost > initial_money: continue if water * per_water_weight + food * per_food_weight > max_weight: continue money = initial_money - cost state_key = (start, 0, water, food, money) if state_key not in visited: visited.add(state_key) # 计算启发值 h = heuristic(start, end, len(weather_sequence), money) states.append((-h, 0, start, (start,), water, food, money, ())) # 批量推入堆 heapq.heapify(queue) for state in states: heapq.heappush(queue, state) best_result = None best_money = 0 # 使用更轻量级的数据结构 visited_ref = set() visited_ref.update(visited) while queue: h, priority, current, path, water, food, money, mining_days = heapq.heappop(queue) current_h = -h # 提前剪枝 if best_money > 0 and current_h < best_money * 0.85: continue # 如果到达终点 if current == end: # 终点退回剩余资源 refund = water * water_price / 2 + food * food_price / 2 money += refund if money > best_money: best_money = money best_result = (list(path), list(mining_days), money) continue # 如果超过最大天数 if priority >= len(weather_sequence): continue # 获取当前天气 weather = weather_sequence[priority] # 计算基础消耗 water_consumption = WEATHER_CONSUMPTION[weather]['water'] food_consumption = WEATHER_CONSUMPTION[weather]['food'] # 优化邻居获取 neighbors = list(G.neighbors(current)) # 1. 在当前区域停留 if node_types[current] in (NODE_TYPES['VILLAGE'], NODE_TYPES['MINE']): if water >= water_consumption and food >= food_consumption: new_water = water - water_consumption new_food = food - food_consumption # 在村庄停留时可以购买资源 if node_types[current] == NODE_TYPES['VILLAGE']: # 计算最大可购买量 max_water_buy = min((max_weight - (new_food * per_food_weight)) // per_water_weight, money // water_price) max_food_buy = min((max_weight - (new_water * per_water_weight)) // per_food_weight, money // food_price) # 使用更高效的大步长 for buy_water in range(0, max_water_buy + 1, 40): for buy_food in range(0, max_food_buy + 1, 40): cost = buy_water * water_price + buy_food * food_price if money < cost: continue new_water2 = new_water + buy_water new_food2 = new_food + buy_food new_money = money - cost # 检查负重 weight = new_water2 * per_water_weight + new_food2 * per_food_weight if weight > max_weight: continue state_key = (current, priority+1, new_water2, new_food2, new_money) if state_key not in visited_ref: visited_ref.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+1) h = heuristic(current, end, remaining_days, new_money) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+1, current, path, new_water2, new_food2, new_money, mining_days) ) else: # 矿山停留但不采矿 state_key = (current, priority+1, new_water, new_food, money) if state_key not in visited_ref: visited_ref.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+1) h = heuristic(current, end, remaining_days, money) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+1, current, path, new_water, new_food, money, mining_days) ) # 2. 移动到相邻区域 for neighbor in neighbors: # 检查资源是否足够一天消耗 if water >= water_consumption and food >= food_consumption: new_water = water - water_consumption new_food = food - food_consumption new_money = money # 在村庄购买资源(到达时立即购买) if node_types[neighbor] == NODE_TYPES['VILLAGE']: # 计算最大可购买量 max_water_buy = min((max_weight - (new_food * per_food_weight)) // per_water_weight, new_money // water_price) max_food_buy = min((max_weight - (new_water * per_water_weight)) // per_food_weight, new_money // food_price) # 使用更高效的大步长 for buy_water in range(0, max_water_buy + 1, 40): for buy_food in range(0, max_food_buy + 1, 40): cost = buy_water * water_price + buy_food * food_price if new_money < cost: continue new_water2 = new_water + buy_water new_food2 = new_food + buy_food new_money2 = new_money - cost # 检查负重 weight = new_water2 * per_water_weight + new_food2 * per_food_weight if weight > max_weight: continue state_key = (neighbor, priority+1, new_water2, new_food2, new_money2) if state_key not in visited_ref: visited_ref.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+1) h = heuristic(neighbor, end, remaining_days, new_money2) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+1, neighbor, path + (neighbor,), new_water2, new_food2, new_money2, mining_days) ) else: # 非村庄节点 state_key = (neighbor, priority+1, new_water, new_food, new_money) if state_key not in visited_ref: visited_ref.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+1) h = heuristic(neighbor, end, remaining_days, new_money) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+1, neighbor, path + (neighbor,), new_water, new_food, new_money, mining_days) ) # 3. 在矿山采矿 if node_types[current] == NODE_TYPES['MINE'] and priority < len(weather_sequence) - 1: # 采矿需要两天时间,消耗两天的资源 total_water = water_consumption * 2 total_food = food_consumption * 2 if water >= total_water and food >= total_food: new_water = water - total_water new_food = food - total_food new_money = money + 1000 # 标记采矿天数 new_mining_days = mining_days + (priority + 1,) # 创建新状态 state_key = (current, priority+2, new_water, new_food, new_money) if state_key not in visited_ref: visited_ref.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+2) h = heuristic(current, end, remaining_days, new_money) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+2, current, path, new_water, new_food, new_money, new_mining_days) ) # 更新全局缓存 if best_money_cache is not None: best_money_cache[(start, end)] = (best_result, best_money) return best_result if best_result else (None, None, 0) # 并行评估所有场景 def evaluate_scenarios_parallel(G, scenarios, start=1, end=25): """优化的并行评估函数""" scenario_results = [] # 使用更大的线程池 with ThreadPoolExecutor(max_workers=12) as executor: futures = [] # 预先计算所有场景 for i, scenario in enumerate(scenarios): future = executor.submit(solve_deterministic_model, G, scenario, start, end) futures.append((i, future)) # 使用更快的进度条 for i, future in enumerate(tqdm(as_completed(futures), total=len(futures), desc="处理场景", ncols=100)): result = future.result() path, mining_days, final_money = result # 计算总行程天数 days = len(scenarios[i]) # 计算路径长度 path_length = len(path) - 1 if path else float('inf') # 记录结果 scenario_results.append({ 'scenario_id': i+1, 'weather_sequence': '→'.join(scenarios[i]), 'path': '→'.join(map(str, path)) if path else '无路径', 'path_length': path_length, 'mining_days': '→'.join(map(str, mining_days)) if mining_days else '无采矿', 'total_days': days, 'final_money': final_money }) return scenario_results def main(): print("=== 5x5地图建模开始 ===") start_time = time.time() # 创建图 G = nx.Graph() # 添加边 for u in range(1, total_regions + 1): for v in range(u + 1, total_regions + 1): if adj_matrix[u][v] == 1: G.add_edge(u, v) # 生成天气场景 print(f"生成 {SCENARIO_COUNT} 个天气场景...") scenarios = generate_weather_scenarios(MAX_DAYS, SCENARIO_COUNT) # 初始化全局缓存 best_money_cache = {} # 评估所有场景 print("评估所有场景...") scenario_results = evaluate_scenarios_parallel(G, scenarios) # 聚合策略 print("聚合策略...") strategies = aggregate_strategies(scenario_results) # 显示结果 display_results(scenario_results, strategies) end_time = time.time() print(f"\n=== 总运行时间: {end_time - start_time:.2f} 秒 ===") if __name__ == "__main__": main()
07-26
结合上述提供完整代码import numpy as np import pandas as pd from tabulate import tabulate import random import math from collections import deque, defaultdict import heapq import networkx as nx from concurrent.futures import ThreadPoolExecutor, as_completed import matplotlib.pyplot as plt from matplotlib.patches import Patch from tqdm import tqdm import time # 配置参数 max_weight = 1200 # kg initial_money = 10000 # 元 # 资源参数 per_water_weight = 3 # kg/箱 water_price = 5 # 元/箱 water_sunny = 3 # 箱/天 water_hot = 9 water_sandstorm = 10 per_food_weight = 2 # kg/箱 food_price = 10 # 元/箱 food_sunny = 4 food_hot = 9 food_sandstorm = 10 # 天气类型和消耗量 WEATHER_TYPES = ['晴朗', '高温', '沙暴'] WEATHER_PROBS = [0.3, 0.5, 0.2] WEATHER_CONSUMPTION = { '晴朗': {'water': water_sunny, 'food': food_sunny}, '高温': {'water': water_hot, 'food': food_hot}, '沙暴': {'water': water_sandstorm, 'food': food_sandstorm} } # 地图参数 rows = 5 # 行数 cols = 5 # 列数 total_regions = rows * cols # 总区域数 # 创建邻接矩阵 adj_matrix = [[0 for _ in range(total_regions + 1)] for _ in range(total_regions + 1)] # 创建连接关系 for region in range(1, total_regions + 1): # 计算当前区域的行和列 row = (region - 1) // cols + 1 col = (region - 1) % cols + 1 # 检查上方邻居 if row > 1: neighbor = region - cols adj_matrix[region][neighbor] = 1 adj_matrix[neighbor][region] = 1 # 检查下方邻居 if row < rows: neighbor = region + cols adj_matrix[region][neighbor] = 1 adj_matrix[neighbor][region] = 1 # 检查左侧邻居 if col > 1: neighbor = region - 1 adj_matrix[region][neighbor] = 1 adj_matrix[neighbor][region] = 1 # 检查右侧邻居 if col < cols: neighbor = region + 1 adj_matrix[region][neighbor] = 1 adj_matrix[neighbor][region] = 1 # 节点类型定义 NODE_TYPES = { 'NORMAL': 0, 'START': 1, # 起点 'MINE': 2, # 矿山 'VILLAGE': 3, # 村庄 'END': 4 # 终点 } # 节点类型初始化 node_types = [NODE_TYPES['NORMAL']] * (total_regions + 1) # 设置特殊节点 node_types[1] = NODE_TYPES['START'] node_types[18] = NODE_TYPES['MINE'] node_types[14] = NODE_TYPES['VILLAGE'] node_types[25] = NODE_TYPES['END'] # 场景生成参数 SCENARIO_COUNT = 50 # 场景数量 MAX_DAYS = 30 # 最大天数 def get_node_type_name(node_type): """根据节点类型值获取名称""" for name, value in NODE_TYPES.items(): if value == node_type: return name return "UNKNOWN" # 创建NetworkX图 G = nx.Graph() # 添加边 for u in range(1, total_regions + 1): for v in range(u + 1, total_regions + 1): if adj_matrix[u][v] == 1: G.add_edge(u, v) # 设置节点颜色 node_colors = [] node_sizes = [] for node in G.nodes(): node_type = node_types[node] if node_type == NODE_TYPES['START']: node_colors.append('limegreen') node_sizes.append(800) elif node_type == NODE_TYPES['MINE']: node_colors.append('gold') node_sizes.append(800) elif node_type == NODE_TYPES['VILLAGE']: node_colors.append('lightcoral') node_sizes.append(700) elif node_type == NODE_TYPES['END']: node_colors.append('darkorange') node_sizes.append(800) else: node_colors.append('skyblue') node_sizes.append(500) # 创建图例 legend_elements = [ Patch(facecolor='limegreen', edgecolor='black', label='起点'), Patch(facecolor='gold', edgecolor='black', label='矿山'), Patch(facecolor='lightcoral', edgecolor='black', label='村庄'), Patch(facecolor='darkorange', edgecolor='black', label='终点'), Patch(facecolor='skyblue', edgecolor='black', label='普通区域'), plt.Line2D([0], [0], color='gray', lw=2, label='可通行路径') ] def generate_weather_scenarios(days, count): """生成指定天数和数量的天气场景""" scenarios = [] for _ in range(count): scenario = random.choices(WEATHER_TYPES, weights=WEATHER_PROBS, k=days) scenarios.append(scenario) return scenarios def heuristic(current, end, remaining_days, money, distance_cache=None): """启发函数,估计从当前状态到终点的潜在收益""" if distance_cache is None: distance_cache = {} # 使用缓存计算最短路径 if (current, end) in distance_cache: distance = distance_cache[(current, end)] else: try: distance = nx.shortest_path_length(G, current, end) distance_cache[(current, end)] = distance except: distance = float('inf') # 如果无法到达终点,只考虑当前金钱 if distance == float('inf'): return money # 否则,考虑剩余天数和可能的采矿收益 potential_mines = max(0, remaining_days - distance) // 2 return money + potential_mines * 1000 def solve_deterministic_model(G, weather_sequence, start=1, end=25, best_money_cache=None): """使用A*算法求解确定性模型,返回最优路径和收益""" # 如果有全局缓存,使用它 if best_money_cache is not None and (start, end) in best_money_cache: best_result, best_money = best_money_cache[(start, end)] if best_money > 0: return best_result # 使用优先队列实现A*算法 queue = [] visited = set() # 初始购买策略(在起点购买资源) max_water = min(max_weight // per_water_weight, initial_money // water_price) max_food = min(max_weight // per_food_weight, initial_money // food_price) # 尝试不同的初始购买组合(增大步长) for water in range(0, max_water + 1, 20): # 步长从10增加到20 for food in range(0, max_food + 1, 20): # 步长从10增加到20 cost = water * water_price + food * food_price if cost > initial_money: continue if water * per_water_weight + food * per_food_weight > max_weight: continue money = initial_money - cost state_key = (start, 0, water, food, money) if state_key in visited: continue visited.add(state_key) # 计算启发值 h = heuristic(start, end, len(weather_sequence), money) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush(queue, (-h, 0, start, [start], water, food, money, [])) best_result = None best_money = 0 # 添加优先级剪枝 best_h = float('-inf') while queue: h, priority, current, path, water, food, money, mining_days = heapq.heappop(queue) current_h = -h # 恢复实际估计值 # 如果当前估计值比已知最优解还差,直接剪枝 if best_money > 0 and current_h < best_money * 0.8: continue # 提前剪枝:如果当前金钱加上最大可能收益仍小于已知最优解 if best_money_cache is not None and (start, end) in best_money_cache: if money + (len(weather_sequence) - priority) * 1000 < best_money_cache[(start, end)][1]: continue # 如果到达终点 if current == end: # 终点退回剩余资源 refund = water * water_price / 2 + food * food_price / 2 money += refund if money > best_money: best_money = money best_result = (path, mining_days, money) continue # 如果超过最大天数 if priority >= len(weather_sequence): continue # 获取当前天气 weather = weather_sequence[priority] # 计算基础消耗 water_consumption = WEATHER_CONSUMPTION[weather]['water'] food_consumption = WEATHER_CONSUMPTION[weather]['food'] # 尝试所有可能的行动 # 1. 在当前区域停留(仅在村庄或矿山有意义) if node_types[current] == NODE_TYPES['VILLAGE'] or node_types[current] == NODE_TYPES['MINE']: if water >= water_consumption and food >= food_consumption: new_water = water - water_consumption new_food = food - food_consumption # 在村庄停留时可以购买资源 if node_types[current] == NODE_TYPES['VILLAGE']: # 计算最大可购买量 max_water_buy = min((max_weight - (new_food * per_food_weight)) // per_water_weight, money // water_price) max_food_buy = min((max_weight - (new_water * per_water_weight)) // per_food_weight, money // food_price) # 尝试购买资源(增大步长) for buy_water in range(0, max_water_buy + 1, 40): # 步长从20增加到40 for buy_food in range(0, max_food_buy + 1, 40): # 步长从20增加到40 cost = buy_water * water_price + buy_food * food_price if money < cost: continue new_water2 = new_water + buy_water new_food2 = new_food + buy_food new_money = money - cost # 检查负重 weight = new_water2 * per_water_weight + new_food2 * per_food_weight if weight > max_weight: continue # 创建新状态 state_key = (current, priority+1, new_water2, new_food2, new_money) if state_key not in visited: visited.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+1) h = heuristic(current, end, remaining_days, new_money) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+1, current, path.copy(), new_water2, new_food2, new_money, mining_days.copy()) ) else: # 矿山停留但不采矿 state_key = (current, priority+1, new_water, new_food, money) if state_key not in visited: visited.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+1) h = heuristic(current, end, remaining_days, money) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+1, current, path.copy(), new_water, new_food, new_money, mining_days.copy()) ) # 2. 移动到相邻区域 for neighbor in G.neighbors(current): # 检查资源是否足够一天消耗 if water >= water_consumption and food >= food_consumption: new_water = water - water_consumption new_food = food - food_consumption new_money = money # 在村庄购买资源(到达时立即购买) if node_types[neighbor] == NODE_TYPES['VILLAGE']: # 计算最大可购买量 max_water_buy = min((max_weight - (new_food * per_food_weight)) // per_water_weight, new_money // water_price) max_food_buy = min((max_weight - (new_water * per_water_weight)) // per_food_weight, new_money // food_price) # 尝试购买资源(增大步长) for buy_water in range(0, max_water_buy + 1, 40): # 步长从20增加到40 for buy_food in range(0, max_food_buy + 1, 40): # 步长从20增加到40 cost = buy_water * water_price + buy_food * food_price if new_money < cost: continue new_water2 = new_water + buy_water new_food2 = new_food + buy_food new_money2 = new_money - cost # 检查负重 weight = new_water2 * per_water_weight + new_food2 * per_food_weight if weight > max_weight: continue # 创建新状态 state_key = (neighbor, priority+1, new_water2, new_food2, new_money2) if state_key not in visited: visited.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+1) h = heuristic(neighbor, end, remaining_days, new_money2) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+1, neighbor, path + [neighbor], new_water2, new_food2, new_money2, mining_days.copy()) ) else: # 非村庄节点 state_key = (neighbor, priority+1, new_water, new_food, new_money) if state_key not in visited: visited.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+1) h = heuristic(neighbor, end, remaining_days, new_money) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+1, neighbor, path + [neighbor], new_water, new_food, new_money, mining_days.copy()) ) # 3. 在矿山采矿(如果当前在矿山) if node_types[current] == NODE_TYPES['MINE'] and priority < len(weather_sequence) - 1: # 采矿需要两天时间,消耗两天的资源 total_water = water_consumption * 2 total_food = food_consumption * 2 if water >= total_water and food >= total_food: new_water = water - total_water new_food = food - total_food new_money = money + 1000 # 采矿收益 # 标记采矿天数 new_mining_days = mining_days.copy() new_mining_days.append(priority + 1) # 记录第二天采矿 # 创建新状态 state_key = (current, priority+2, new_water, new_food, new_money) if state_key not in visited: visited.add(state_key) # 计算启发值 remaining_days = len(weather_sequence) - (priority+2) h = heuristic(current, end, remaining_days, new_money) # 优先级是( - 总收益估计, 实际金钱, 当前天数) heapq.heappush( queue, (-h, priority+2, current, path.copy(), new_water, new_food, new_money, new_mining_days) ) # 更新全局缓存 if best_money_cache is not None: best_money_cache[(start, end)] = (best_result, best_money) return best_result if best_result else (None, None, 0) # 场景评估函数 def evaluate_scenarios(G, scenarios, start=1, end=25): """评估所有场景,返回每个场景的最优解""" scenario_results = [] distance_cache = {} # 缓存最短路径计算 best_money_cache = {} # 缓存最佳金钱结果 # 添加进度条 for i, scenario in enumerate(tqdm(scenarios, desc="处理场景")): # 求解该场景的最优策略 path, mining_days, final_money = solve_deterministic_model(G, scenario, start, end, best_money_cache) # 计算总行程天数 days = len(scenario) # 计算路径长度 path_length = len(path) - 1 if path else float('inf') # 记录结果 - 完整输出天气序列和路径 scenario_results.append({ 'scenario_id': i+1, 'weather_sequence': '→'.join(scenario), # 完整天气序列 'path': '→'.join(map(str, path)) if path else '无路径', # 完整路径 'path_length': path_length, 'mining_days': '→'.join(map(str, mining_days)) if mining_days else '无采矿', 'total_days': days, 'final_money': final_money }) return scenario_results # 并行评估所有场景 def evaluate_scenarios_parallel(G, scenarios, start=1, end=25): """并行评估所有场景""" scenario_results = [] with ThreadPoolExecutor(max_workers=8) as executor: # 增加线程数到8 futures = [] for i, scenario in enumerate(scenarios): future = executor.submit(solve_deterministic_model, G, scenario, start, end) futures.append((i, future)) for i, future in enumerate(tqdm(as_completed(futures), total=len(futures), desc="处理场景")): result = future.result() path, mining_days, final_money = result # 计算总行程天数 days = len(scenarios[i]) # 计算路径长度 path_length = len(path) - 1 if path else float('inf') # 记录结果 scenario_results.append({ 'scenario_id': i+1, 'weather_sequence': '→'.join(scenarios[i]), # 完整天气序列 'path': '→'.join(map(str, path)) if path else '无路径', # 完整路径 'path_length': path_length, 'mining_days': '→'.join(map(str, mining_days)) if mining_days else '无采矿', 'total_days': days, 'final_money': final_money }) return scenario_results # 策略聚合函数 def aggregate_strategies(results): """聚合场景结果,生成不同策略""" # 转换为DataFrame df = pd.DataFrame(results) # 过滤无效结果 valid_df = df[df['final_money'] > 0] if len(valid_df) == 0: return None # 1. 期望最优策略(平均资金最高) expected_optimal = valid_df.loc[valid_df['final_money'].idxmax()] # 2. 最坏情况最优(最差场景中表现最好) worst_case_optimal = valid_df.sort_values('final_money').iloc[0] # 3. 鲁棒策略(最差20%场景中表现最好的) robust_df = valid_df.sort_values('final_money').iloc[:max(1, len(valid_df)//5)] robust_strategy = robust_df.sort_values('final_money').iloc[-1] return { 'expected_optimal': expected_optimal, 'worst_case_optimal': worst_case_optimal, 'robust_strategy': robust_strategy} # 结果展示函数 def display_results(results, strategies): """显示结果表格""" # 转换为DataFrame df = pd.DataFrame(results) # 打印统计信息 print("\n=== 场景统计信息 ===") valid_count = len(df[df['final_money'] > 0]) print(f"有效场景数: {valid_count}/{len(df)}") if valid_count > 0: valid_df = df[df['final_money'] > 0] print(f"平均剩余资金: {valid_df['final_money'].mean():.2f} 元") print(f"最低剩余资金: {valid_df['final_money'].min()} 元") print(f"最高剩余资金: {valid_df['final_money'].max()} 元") print(f"平均路径长度: {valid_df['path_length'].mean():.2f} 步") # 打印策略对比 if strategies: print("\n=== 策略对比 ===") strategy_table = [] for strategy_name, row in strategies.items(): strategy_table.append([ strategy_name, row['final_money'], row['path'], row['mining_days'], row['total_days'] ]) print(tabulate(strategy_table, headers=[ '策略类型', '剩余资金(元)', '路径', '采矿天数', '总天数' ], tablefmt='grid')) # 保存为Excel output_file = "5x5地图结果.xlsx" df.to_excel(output_file, index=False) print(f"\n所有场景结果已保存至 '{output_file}'") def draw_map(layout, title, filename): """绘制地图""" plt.figure(figsize=(14, 12)) # 选择布局 if layout == 'circular': pos = nx.circular_layout(G) elif layout == 'spring': pos = nx.spring_layout(G, seed=42, k=0.3) elif layout == 'grid': # 自定义网格布局 pos = {} for region in range(1, total_regions + 1): row = (region - 1) // cols col = (region - 1) % cols pos[region] = np.array([col, -row]) else: pos = nx.spring_layout(G, seed=42) # 绘制图形 nx.draw_networkx_nodes(G, pos, node_color=node_colors, node_size=node_sizes, alpha=0.9) nx.draw_networkx_edges(G, pos, edge_color='gray', width=1.5, alpha=0.7) nx.draw_networkx_labels(G, pos, font_size=10, font_weight='bold') # 添加图例和标题 plt.legend(handles=legend_elements, loc='upper right', fontsize=10, bbox_to_anchor=(1.15, 1), framealpha=1) plt.title(f"沙漠寻宝地图 - {title}", fontsize=16, pad=20) plt.text(0.5, -0.1, "注:连线表示区域间可直接移动", ha='center', transform=plt.gca().transAxes, fontsize=10) # 显示和保存 plt.grid(False) plt.axis('off') plt.tight_layout() plt.savefig(filename, dpi=300, bbox_inches='tight') plt.show() def main(): print("=== 5x5地图建模开始 ===") # 创建图 G = nx.Graph() # 添加边 for u in range(1, total_regions + 1): for v in range(u + 1, total_regions + 1): if adj_matrix[u][v] == 1: G.add_edge(u, v) # 生成天气场景 print(f"生成 {SCENARIO_COUNT} 个天气场景...") scenarios = generate_weather_scenarios(MAX_DAYS, SCENARIO_COUNT) # 评估所有场景 print("评估所有场景...") scenario_results = evaluate_scenarios_parallel(G, scenarios) # 改用并行处理 # 聚合策略 print("聚合策略...") strategies = aggregate_strategies(scenario_results) # 显示结果 display_results(scenario_results, strategies) # 绘制地图 print("绘制地图...") draw_map('circular', '环形布局', 'desert_game_map_circular.png') draw_map('spring', '力导向布局', 'desert_game_map_spring.png') draw_map('grid', '网格布局', 'desert_game_map_grid.png') print("\n=== 建模完成 ===") if __name__ == "__main__": main()
07-26
String filePath=""; File file=new File(filePath); //解决乱码问题 String filename=URLEncoder.encode(file.getName(),"utf-8"); //重置输出流 response.reset(); Response.AddHeader("Content-Disposition", "attachment;filename="+filename);//设置文件名 response.addHeader("Content-Length",file.length);//设置下载文件大小 response.setContentType("application/octet-stream");//设置文件类型 OutputStream toClient=new BufferedOuntputStream( response.getOutputStream() );//获取二进制输出流 //读取文件数据 InputStream fis=new BufferedInputStream(new FileInputStream(filePath)); byte[] buffer=new byte[file.length()]; fis.read(buffer); fis.close(); //输出文件数据 toClient.write(buffer); toClient.close(); 文件类型如下: ".*"="application/octet-stream" ".001"="application/x-001" ".301"="application/x-301" ".323"="text/h323" ".906"="application/x-906" ".907"="drawing/907" ".a11"="application/x-a11" ".acp"="audio/x-mei-aac" ".ai"="application/postscript" ".aif"="audio/aiff" ".aifc"="audio/aiff" ".aiff"="audio/aiff" ".anv"="application/x-anv" ".asa"="text/asa" ".asf"="video/x-ms-asf" ".asp"="text/asp" ".asx"="video/x-ms-asf" ".au"="audio/basic" ".avi"="video/avi" ".awf"="application/vnd.adobe.workflow" ".biz"="text/xml" ".bmp"="application/x-bmp" ".bot"="application/x-bot" ".c4t"="application/x-c4t" ".c90"="application/x-c90" ".cal"="application/x-cals" ".cat"="application/vnd.ms-pki.seccat" ".cdf"="application/x-netcdf" ".cdr"="application/x-cdr" ".cel"="application/x-cel" ".cer"="application/x-x509-ca-cert" ".cg4"="application/x-g4" ".cgm"="application/x-cgm" ".cit"="application/x-cit" ".class"="java/*" ".cml"="text/xml" ".cmp"="application/x-cmp" ".cmx"="application/x-cmx" ".cot"="application/x-cot" ".crl"="application/pkix-crl" ".crt"="application/x-x509-ca-cert" ".csi"="application/x-csi" ".css"="text/css" ".cut"="application/x-cut" ".dbf"="application/x-dbf" ".dbm"="application/x-dbm" ".dbx"="application/x-dbx" ".dcd"="text/xml" ".dcx"="application/x-dcx" ".der"="application/x-x509-ca-cert" ".dgn"="application/x-dgn" ".dib"="application/x-dib" ".dll"="application/x-msdownload" ".doc"="application/msword" ".dot"="application/msword" ".drw"="application/x-drw" ".dtd"="text/xml" ".dwf"="Model/vnd.dwf" ".dwf"="application/x-dwf" ".dwg"="application/x-dwg" ".dxb"="application/x-dxb" ".dxf"="application/x-dxf" ".edn"="application/vnd.adobe.edn" ".emf"="application/x-emf" ".eml"="message/rfc822" ".ent"="text/xml" ".epi"="application/x-epi" ".eps"="application/x-ps" ".eps"="application/postscript" ".etd"="application/x-ebx" ".exe"="application/x-msdownload" ".fax"="image/fax" ".fdf"="application/vnd.fdf" ".fif"="application/fractals" ".fo"="text/xml" ".frm"="application/x-frm" ".g4"="application/x-g4" ".gbr"="application/x-gbr" ".gcd"="application/x-gcd" ".gif"="image/gif" ".gl2"="application/x-gl2" ".gp4"="application/x-gp4" ".hgl"="application/x-hgl" ".hmr"="application/x-hmr" ".hpg"="application/x-hpgl" ".hpl"="application/x-hpl" ".hqx"="application/mac-binhex40" ".hrf"="application/x-hrf" ".hta"="application/hta" ".htc"="text/x-component" ".htm"="text/html" ".html"="text/html" ".htt"="text/webviewhtml" ".htx"="text/html" ".icb"="application/x-icb" ".ico"="image/x-icon" ".ico"="application/x-ico" ".iff"="application/x-iff" ".ig4"="application/x-g4" ".igs"="application/x-igs" ".iii"="application/x-iphone" ".img"="application/x-img" ".ins"="application/x-internet-signup" ".isp"="application/x-internet-signup" ".IVF"="video/x-ivf" ".java"="java/*" ".jfif"="image/jpeg" ".jpe"="image/jpeg" ".jpe"="application/x-jpe" ".jpeg"="image/jpeg" ".jpg"="image/jpeg" ".jpg"="application/x-jpg" ".js"="application/x-javascript" ".jsp"="text/html" ".la1"="audio/x-liquid-file" ".lar"="application/x-laplayer-reg" ".latex"="application/x-latex" ".lavs"="audio/x-liquid-secure" ".lbm"="application/x-lbm" ".lmsff"="audio/x-la-lms" ".ls"="application/x-javascript" ".ltr"="application/x-ltr" ".m1v"="video/x-mpeg" ".m2v"="video/x-mpeg" ".m3u"="audio/mpegurl" ".m4e"="video/mpeg4" ".mac"="application/x-mac" ".man"="application/x-troff-man" ".math"="text/xml" ".mdb"="application/msaccess" ".mdb"="application/x-mdb" ".mfp"="application/x-shockwave-flash" ".mht"="message/rfc822" ".mhtml"="message/rfc822" ".mi"="application/x-mi" ".mid"="audio/mid" ".midi"="audio/mid" ".mil"="application/x-mil" ".mml"="text/xml" ".mnd"="audio/x-musicnet-download" ".mns"="audio/x-musicnet-stream" ".mocha"="application/x-javascript" ".movie"="video/x-sgi-movie" ".mp1"="audio/mp1" ".mp2"="audio/mp2" ".mp2v"="video/mpeg" ".mp3"="audio/mp3" ".mp4"="video/mpeg4" ".mpa"="video/x-mpg" ".mpd"="application/vnd.ms-project" ".mpe"="video/x-mpeg" ".mpeg"="video/mpg" ".mpg"="video/mpg" ".mpga"="audio/rn-mpeg" ".mpp"="application/vnd.ms-project" ".mps"="video/x-mpeg" ".mpt"="application/vnd.ms-project" ".mpv"="video/mpg" ".mpv2"="video/mpeg" ".mpw"="application/vnd.ms-project" ".mpx"="application/vnd.ms-project" ".mtx"="text/xml" ".mxp"="application/x-mmxp" ".net"="image/pnetvue" ".nrf"="application/x-nrf" ".nws"="message/rfc822" ".odc"="text/x-ms-odc" ".out"="application/x-out" ".p10"="application/pkcs10" ".p12"="application/x-pkcs12" ".p7b"="application/x-pkcs7-certificates" ".p7c"="application/pkcs7-mime" ".p7m"="application/pkcs7-mime" ".p7r"="application/x-pkcs7-certreqresp" ".p7s"="application/pkcs7-signature" ".pc5"="application/x-pc5" ".pci"="application/x-pci" ".pcl"="application/x-pcl" ".pcx"="application/x-pcx" ".pdf"="application/pdf" ".pdf"="application/pdf" ".pdx"="application/vnd.adobe.pdx" ".pfx"="application/x-pkcs12" ".pgl"="application/x-pgl" ".pic"="application/x-pic" ".pko"="application/vnd.ms-pki.pko" ".pl"="application/x-perl" ".plg"="text/html" ".pls"="audio/scpls" ".plt"="application/x-plt" ".png"="image/png" ".png"="application/x-png" ".pot"="application/vnd.ms-powerpoint" ".ppa"="application/vnd.ms-powerpoint" ".ppm"="application/x-ppm" ".pps"="application/vnd.ms-powerpoint" ".ppt"="application/vnd.ms-powerpoint" ".ppt"="application/x-ppt" ".pr"="application/x-pr" ".prf"="application/pics-rules" ".prn"="application/x-prn" ".prt"="application/x-prt" ".ps"="application/x-ps" ".ps"="application/postscript" ".ptn"="application/x-ptn" ".pwz"="application/vnd.ms-powerpoint" ".r3t"="text/vnd.rn-realtext3d" ".ra"="audio/vnd.rn-realaudio" ".ram"="audio/x-pn-realaudio" ".ras"="application/x-ras" ".rat"="application/rat-file" ".rdf"="text/xml" ".rec"="application/vnd.rn-recording" ".red"="application/x-red" ".rgb"="application/x-rgb" ".rjs"="application/vnd.rn-realsystem-rjs" ".rjt"="application/vnd.rn-realsystem-rjt" ".rlc"="application/x-rlc" ".rle"="application/x-rle" ".rm"="application/vnd.rn-realmedia" ".rmf"="application/vnd.adobe.rmf" ".rmi"="audio/mid" ".rmj"="application/vnd.rn-realsystem-rmj" ".rmm"="audio/x-pn-realaudio" ".rmp"="application/vnd.rn-rn_music_package" ".rms"="application/vnd.rn-realmedia-secure" ".rmvb"="application/vnd.rn-realmedia-vbr" ".rmx"="application/vnd.rn-realsystem-rmx" ".rnx"="application/vnd.rn-realplayer" ".rp"="image/vnd.rn-realpix" ".rpm"="audio/x-pn-realaudio-plugin" ".rsml"="application/vnd.rn-rsml" ".rt"="text/vnd.rn-realtext" ".rtf"="application/msword" ".rtf"="application/x-rtf" ".rv"="video/vnd.rn-realvideo" ".sam"="application/x-sam" ".sat"="application/x-sat" ".sdp"="application/sdp" ".sdw"="application/x-sdw" ".sit"="application/x-stuffit" ".slb"="application/x-slb" ".sld"="application/x-sld" ".slk"="drawing/x-slk" ".smi"="application/smil" ".smil"="application/smil" ".smk"="application/x-smk" ".snd"="audio/basic" ".sol"="text/plain" ".sor"="text/plain" ".spc"="application/x-pkcs7-certificates" ".spl"="application/futuresplash" ".spp"="text/xml" ".ssm"="application/streamingmedia" ".sst"="application/vnd.ms-pki.certstore" ".stl"="application/vnd.ms-pki.stl" ".stm"="text/html" ".sty"="application/x-sty" ".svg"="text/xml" ".swf"="application/x-shockwave-flash" ".tdf"="application/x-tdf" ".tg4"="application/x-tg4" ".tga"="application/x-tga" ".tif"="image/tiff" ".tif"="application/x-tif" ".tiff"="image/tiff" ".tld"="text/xml" ".top"="drawing/x-top" ".torrent"="application/x-bittorrent" ".tsd"="text/xml" ".txt"="text/plain" ".uin"="application/x-icq" ".uls"="text/iuls" ".vcf"="text/x-vcard" ".vda"="application/x-vda" ".vdx"="application/vnd.visio" ".vml"="text/xml" ".vpg"="application/x-vpeg005" ".vsd"="application/vnd.visio" ".vsd"="application/x-vsd" ".vss"="application/vnd.visio" ".vst"="application/vnd.visio" ".vst"="application/x-vst" ".vsw"="application/vnd.visio" ".vsx"="application/vnd.visio" ".vtx"="application/vnd.visio" ".vxml"="text/xml" ".wav"="audio/wav" ".wax"="audio/x-ms-wax" ".wb1"="application/x-wb1" ".wb2"="application/x-wb2" ".wb3"="application/x-wb3" ".wbmp"="image/vnd.wap.wbmp" ".wiz"="application/msword" ".wk3"="application/x-wk3" ".wk4"="application/x-wk4" ".wkq"="application/x-wkq" ".wks"="application/x-wks" ".wm"="video/x-ms-wm" ".wma"="audio/x-ms-wma" ".wmd"="application/x-ms-wmd" ".wmf"="application/x-wmf" ".wml"="text/vnd.wap.wml" ".wmv"="video/x-ms-wmv" ".wmx"="video/x-ms-wmx" ".wmz"="application/x-ms-wmz" ".wp6"="application/x-wp6" ".wpd"="application/x-wpd" ".wpg"="application/x-wpg" ".wpl"="application/vnd.ms-wpl" ".wq1"="application/x-wq1" ".wr1"="application/x-wr1" ".wri"="application/x-wri" ".wrk"="application/x-wrk" ".ws"="application/x-ws" ".ws2"="application/x-ws" ".wsc"="text/scriptlet" ".wsdl"="text/xml" ".wvx"="video/x-ms-wvx" ".xdp"="application/vnd.adobe.xdp" ".xdr"="text/xml" ".xfd"="application/vnd.adobe.xfd" ".xfdf"="application/vnd.adobe.xfdf" ".xhtml"="text/html" ".xls"="application/vnd.ms-excel" ".xls"="application/x-xls" ".xlw"="application/x-xlw" ".xml"="text/xml" ".xpl"="audio/scpls" ".xq"="text/xml" ".xql"="text/xml" ".xquery"="text/xml" ".xsd"="text/xml" ".xsl"="text/xml" ".xslt"="text/xml" ".xwd"="application/x-xwd" ".x_b"="application/x-x_b" ".x_t"="application/x-x_t"
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值