前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ASP.NET Core | 笔记

ASP.NET Core | 笔记

作者头像
yiyun
发布2022-04-01 16:49:43
4.6K0
发布2022-04-01 16:49:43
举报
文章被收录于专栏:yiyun 的专栏

引言

参考:

依赖注入

注入对相同接口的实现: 不一定会替换,如果通过 TryAddxxxx 注册,那么后面注册的无效(会判断是否已经存在实现,若有则不再添加)。 如果使用Addxxx注册,相同的接口将放在一个字典中,然后解析服务的时候解析最后一个。 但是之前注册的依然还在,可以通过遍历Services可以获取所有注册的接口。

依赖注入

AOP

Q:

A:

ASP.NET Core 中的静态文件

参考:

断点续传

参考:

WebSocket

参考:

发布

参考:

代码语言:javascript
复制
dotnet publish [<PROJECT>|<SOLUTION>] [-a|--arch <ARCHITECTURE>]
    [-c|--configuration <CONFIGURATION>]
    [-f|--framework <FRAMEWORK>] [--force] [--interactive]
    [--manifest <PATH_TO_MANIFEST_FILE>] [--no-build] [--no-dependencies]
    [--no-restore] [--nologo] [-o|--output <OUTPUT_DIRECTORY>]
    [--os <OS>] [-r|--runtime <RUNTIME_IDENTIFIER>]
    [--self-contained [true|false]]
    [--no-self-contained] [-v|--verbosity <LEVEL>]
    [--version-suffix <VERSION_SUFFIX>]

dotnet publish -h|--help

在 ASP.NET Core 中 启用跨域

参考:

同一源 如果两个 URL 具有相同的方案、主机和端口,则它们具有相同的源 (RFC 6454) 。 这两个 URL 具有相同的来源:

  • https://example.com/foo.html
  • https://example.com/bar.html

这些 URL 的源与前两个 URL 不同:

  • https://example.net:不同的域
  • https://www.example.com/foo.html:不同的子域
  • http://example.com/foo.html:不同的方案
  • https://example.com:9000/foo.html:不同的端口

启用 CORS 有三种方法可以启用 CORS:

将 [EnableCors] 属性与命名策略一起使用在限制支持 CORS 的终结点方面提供了最佳控制。 警告 UseCors 必须按正确的顺序调用 。 有关详细信息,请参阅 中间件顺序。 例如, UseCors 在使用 之前必须 UseResponseCaching 调用 UseResponseCaching

UseCors 添加 CORS 中间件。

  • 正确的 UseCors 调用必须位于 之后 UseRouting ,但在 之前 UseAuthorization 。 有关详细信息,请参阅 中间件顺序
代码语言:javascript
复制
app.UseRouting();
app.UseCors();

使用默认策略和中间件的 CORS

代码语言:javascript
复制
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    // 注意: AddDefaultPolicy
    options.AddDefaultPolicy(
        builder =>
        {
            builder.WithOrigins("http://*.example.com",
                                "http://www.contoso.com");
        });
});

builder.Services.AddControllers();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

// 注意: UseCors(), 没有指定 CorsPolicyName
app.UseCors();

app.UseAuthorization();

app.MapControllers();

app.Run();

补充:

使用默认策略, 允许任意跨域

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    // 任意跨域
    services.AddCors(options =>
    {
        options.AddDefaultPolicy(policyBuilder =>
        {
            policyBuilder.AllowAnyHeader()
                .AllowAnyMethod()
                .AllowAnyOrigin();
        });
    });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();
    // 注意
    app.UseCors();

    app.UseDefaultFiles();
    app.UseStaticFiles();

    app.UseAuthorization();
}

预检请求 preflight-requests

参考:

对于某些 CORS 请求,浏览器会在发出实际请求之前发送额外的 OPTIONS 请求。 此请求称为 预检请求。 如果满足以下 所有 条件,浏览器可以跳过预检请求:

  • 请求方法为 GET、HEAD 或 POST。
  • 应用不会设置、、、或以外的请求标头 Accept Accept-Language Content-Language Content-Type Last-Event-ID
  • Content-Type 标头(如果已设置)具有以下值之一:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

设置预检过期时间

Access-Control-Max-Age标头指定可以缓存对预检请求的响应的多久。 若要设置此标头,请调用 SetPreflightMaxAge

代码语言:javascript
复制
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("MySetPreflightExpirationPolicy",
        builder =>
        {
            builder.WithOrigins("http://example.com")
                   .SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
        });
});

builder.Services.AddControllers();

var app = builder.Build();

使用终结点路由和 [HttpOptions] 测试 CORS

使用 基于每个终结点启用 CORS RequireCors 目前 不支持自动预检请求

请考虑以下代码,该代码使用终结点路由来启用 CORS:

代码语言:javascript
复制
// OPTIONS: api/TodoItems2/5
[HttpOptions("{id}")]
public IActionResult PreflightRoute(int id)
{
    return NoContent();
}

这时就无法自动响应预检请求,于是需要显式 响应 OPTIONS

Q&A

补充

SSH

参考:

使用ssh客户端连接远程主机执行命令,并拿到输出结果:

代码语言:javascript
复制
using (var sshClient = new SshClient("host", port,"username", "password"))
{
    sshClient.Connect();
    using (var cmd = sshClient.CreateCommand("ls -l"))
    {
        var res = cmd.Execute();
        Console.Write(res);
    }
}

使用sftp客户端上传文件:

代码语言:javascript
复制
using (var sftpClient = new SftpClient("host", port,"username", "password"))
{
    sftpClient.Connect();
    sftpClient.UploadFile(File.Open(@"D:\index.html", FileMode.Open),"/root/index.html");
}

下载文件:

代码语言:javascript
复制
using (var sftpClient = new SftpClient("host", port,"username", "password"))
{
    sftpClient.Connect();
    using (var stream = File.Open(@"F:\index.html", FileMode.OpenOrCreate))
    {
        sftpClient.DownloadFile("/root/index.html", stream);
    }
}

System.NullReferenceException: WebApi.Startup.ConfigureServices(IServiceCollection services)

参考:

代码语言:javascript
复制
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at WebApi.Startup.ConfigureServices(IServiceCollection services) in F:\Com\me\Repos\OneTree\src\Framework\Presentation\WebApi\Startup.cs:line 58
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.InvokeCore(Object instance, IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.<>c__DisplayClass9_0.<Invoke>g__Startup|0(IServiceCollection serviceCollection)
   at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.Invoke(Object instance, IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.<>c__DisplayClass8_0.<Build>b__0(IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.UseStartup(Type startupType, HostBuilderContext context, IServiceCollection services)
   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass12_0.<UseStartup>b__0(HostBuilderContext context, IServiceCollection services)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at WebApi.Program.Main(String[] args) in F:\Com\me\Repos\OneTree\src\Framework\Presentation\WebApi\Program.cs:line 31

发现,当前不在 WebApi.dll 所处目录,通过 绝对路径 方式运行,会由于找不到 appsettings.json,而导致 _configurationnull 解决: 前往 WebApi.dll 所处目录,运行 dotnet WebApi.dll即可

MySql.Data.EntityFrameworkCore 8.0.22 仅与 Microsoft.EntityFrameworkCore 3.1 兼容

参考:

MySql.Data.EntityFrameworkCore 8.0.22 仅与 Microsoft.EntityFrameworkCore 3.1 兼容。将所有 Microsoft.EntityFramework 包从 5.0.0 降级到 3.1.10 以修复错误。 随着 MySQL Connector/NET 8.0.23 于 2021 年 1 月 18 日的发布,Oracle 现在发布了一个与 Microsoft.EntityFramework 5.0 兼容的不同 NuGet 包:MySql.EntityFrameworkCore。 请参阅此处的版本兼容性表。 或者,您可以尝试切换到Pomelo.EntityFrameworkCore.MySql 5.0.0-alpha.2(或更高版本);请参阅其兼容包版本表

插件系统

参考:

加载 ControllerView

代码语言:javascript
复制
var assembly = ...;
services.AddMvc()
    .AddApplicationPart(assembly)

View

代码语言:javascript
复制
services.AddMvc().ConfigureApplicationPartManager(apm =>
    {
    foreach (var b in new CompiledRazorAssemblyApplicationPartFactory().GetApplicationParts(AssemblyLoadContext.Default.LoadFromAssemblyPath(".../ViewAssembypath/file.Views.dll")))
        apm.ApplicationParts.Add(b);
    });

合并dll

参考:

WPF 集成 ASP.NET Core

参考:

WebView

参考:

进程管理

参考:

代码语言:javascript
复制
public void FrpStart()
{
    if (p != null)
    {
        MessageBox.Show("进程已存在");
        return;
    }
    p = new Process
    {
        // Configure the process using the StartInfo properties.
        StartInfo =
            {
            	//调用的程序名称,比如windows下的cmd,linux下的sh或者bash,即这里要填写控制台程序的路径
                FileName = Utils.GetTempPath() + "/frpc.exe",
                //参数,MainConfig为配置文件路径
                Arguments = "-c " + MainConfig,
                //控制台程序所在的路径
                WorkingDirectory = Utils.GetTempPath(),
                WindowStyle = ProcessWindowStyle.Hidden,
                UseShellExecute = false,
                CreateNoWindow = true,
                //重定向输入输出
                RedirectStandardInput = true,
                RedirectStandardOutput = true
            }
    };
    //监听控制台的输出
    p.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
    {
        // Prepend line numbers to each line of the output.
        if (!string.IsNullOrEmpty(e.Data))
        {
            append(e.Data);
        }
    });
    p.Start();
    p.BeginOutputReadLine();
}

注意上面新建进程的参数UseShellExecute = false,如果这里设置为false,那么FileName这个参数中控制台程序的只能用绝对路径,即WorkingDirectory参数无效。 如果不设置UseShellExecute为false,则无法重定向输出。 如果UseShellExecute = true,则FileName可以直接使用控制台程序的名字,前提是WorkingDirectory里面的路径是正确的。

代码语言:javascript
复制
public void FrpStart()
{
	//检测是否存在残留的线程,并将其关闭
    Process[] existingPrivoxy = Process.GetProcessesByName("frpc");
    foreach (Process p in existingPrivoxy)
    {
        KillProcess(p);
    }
	..........
    p.Start();
    p.BeginOutputReadLine();
    //将其加入Job
    //Job的初始化省略了,可以在构造函数初始化,使用单例模式
    Job.AddProcess(p.Handle);
}

private static void KillProcess(Process p)
{
    try
    {
        p.CloseMainWindow();
        p.WaitForExit(100);
        if (!p.HasExited)
        {
            p.Kill();
            p.WaitForExit();
        }
    }
    catch (Exception e)
    {
    }
}

HttpClient 上传文件

代码语言:javascript
复制
public int UpSound_Request(string address, string fileNamePath, string saveName, ProgressBar progressBar)
{
    int returnValue = 0;
    //要上传的文件
    FileStream fs = new FileStream(fileNamePath, FileMode.Open, FileAccess.Read);
    //二进制对象
    BinaryReader r = new BinaryReader(fs);
    //时间戳
    string strBoundary = "----------" + DateTime.Now.Ticks.ToString("x");
    byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + strBoundary + "\r\n");
    //请求的头部信息
    StringBuilder sb = new StringBuilder();
    sb.Append("--");
    sb.Append(strBoundary);
    sb.Append("\r\n");
    sb.Append("Content-Disposition: form-data; name=\"");
    sb.Append("file");
    sb.Append("\"; filename=\"");
    sb.Append(saveName);
    sb.Append("\";");
    sb.Append("\r\n");
    sb.Append("Content-Type: ");
    sb.Append("application/octet-stream");
    sb.Append("\r\n");
    sb.Append("\r\n");
    string strPostHeader = sb.ToString();
    byte[] postHeaderBytes = Encoding.UTF8.GetBytes(strPostHeader);
    // 根据uri创建HttpWebRequest对象   
    HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(new Uri(address));
    httpReq.Method = "POST";
    //对发送的数据不使用缓存   
    httpReq.AllowWriteStreamBuffering = false;
    //设置获得响应的超时时间(300秒)   
    httpReq.Timeout = 300000;
    httpReq.ContentType = "multipart/form-data; boundary=" + strBoundary;
    long length = fs.Length + postHeaderBytes.Length + boundaryBytes.Length;
    long fileLength = fs.Length;
    httpReq.ContentLength = length;
    try
    {
        progressBar.Maximum = int.MaxValue;
        progressBar.Minimum = 0;
        progressBar.Value = 0;
        //每次上传400k  
        int bufferLength = 409600;
        byte[] buffer = new byte[bufferLength]; //已上传的字节数   
        long offset = 0;         //开始上传时间   
        DateTime startTime = DateTime.Now;
        int size = r.Read(buffer, 0, bufferLength);
        Stream postStream = httpReq.GetRequestStream();         //发送请求头部消息   
        postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
        while (size > 0)
        {
            postStream.Write(buffer, 0, size);
            offset += size;
            progressBar.Value = (int)(offset * (int.MaxValue / length));
            TimeSpan span = DateTime.Now - startTime;
            double second = span.TotalSeconds;
            labTime.Text = "已用时:" + second.ToString("F2") + "秒";
            if (second > 0.001)
            {
                labSpeed.Text = "平均速度:" + (offset / 1024 / second).ToString("0.00") + "KB/秒";
            }
            else
            {
                labSpeed.Text = " 正在连接…";
            }
            labState.Text = "已上传:" + (offset * 100.0 / length).ToString("F2") + "%";
            labSize.Text = (offset / 1048576.0).ToString("F2") + "M/" + (fileLength / 1048576.0).ToString("F2") + "M";
            Application.DoEvents();
            size = r.Read(buffer, 0, bufferLength);
        }
        //添加尾部的时间戳   
        postStream.Write(boundaryBytes, 0, boundaryBytes.Length);
        postStream.Close();
        //获取服务器端的响应   
        WebResponse webRespon = httpReq.GetResponse();
        Stream s = webRespon.GetResponseStream();
        //读取服务器端返回的消息  
        StreamReader sr = new StreamReader(s);
        String sReturnString = sr.ReadLine();
        s.Close();
        sr.Close();
        if (sReturnString == "Success")
        {
            returnValue = 1;
        }
        else if (sReturnString == "Error")
        {
            returnValue = 0;
        }
    }
    catch
    {
        returnValue = 0;
    }
    finally
    {
        fs.Close();
        r.Close();
    }
    return returnValue;
}

通过流式传输上传大型文件

参考:

解析 nuget 的 nupkg

参考:

自定义模板

参考:

JavaScript 拦截请求

参考:

创建 nuget 源代码 、符号包

参考:

良好的调试体验依赖于调试符号的存在,因为它们提供了一些关键信息,例如已编译的代码与源代码之间的关联、局部变量的名称、堆栈跟踪等。 你可以使用符号包 (.snupkg) 来分发这些符号,并改善 NuGet 包的调试体验。 请注意,符号包并不是使调试符号可用于库使用者的唯一策略。 还可以通过以下项目属性在 dllexeembed 它们:<DebugType>embedded</DebugType>

创建符号包

如果使用 dotnet CLI 或 MSBuild,则除 .nupkg 文件外,还需要设置 IncludeSymbolsSymbolPackageFormat 属性以创建 .snupkg 文件。

  • 要么将以下属性添加到 .csproj 文件:
代码语言:javascript
复制
<PropertyGroup>
    <IncludeSymbols>true</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
  • 要么在命令行上指定这些属性:
代码语言:javascript
复制
dotnet pack MyPackage.csproj -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg

代码语言:javascript
复制
msbuild MyPackage.csproj /t:pack /p:IncludeSymbols=true /p:SymbolPackageFormat=snupkg

如果使用 NuGet.exe,除 .nupkg 文件外,可以使用以下命令创建一个 .snupkg 文件:

代码语言:javascript
复制
nuget pack MyPackage.nuspec -Symbols -SymbolPackageFormat snupkg

nuget pack MyPackage.csproj -Symbols -SymbolPackageFormat snupkg

发布符号包

  1. 为方便起见,首先使用 NuGet 保存 API 密钥(请参阅发布包)。
代码语言:javascript
复制
nuget SetApiKey Your-API-Key
  1. 将主包发布到 nuget.org 后,按如下方式推送符号包。
代码语言:javascript
复制
nuget push MyPackage.snupkg
  1. 还可以 使用以下命令__同时推送主包和符号包__。 当前文件夹中必须同时有 .nupkg 和 .snupkg 文件。
代码语言:javascript
复制
nuget push MyPackage.nupkg

NuGet 会将两个包发布到 nuget.org。MyPackage.nupkg 先发布,随后 MyPackage.snupkg 发布。

备注 如果没有发布符号包,请检查是否已将 NuGet.org 源配置为 https://api.nuget.org/v3/index.json。 只有 NuGet V3 API 才支持符号包发布。

WebTerm

参考:

拦截方法

参考:

下载文件

参考:

Web 在线代理

参考:

WebAPI 在线文档

Swashbuckle

参考:

代码语言:javascript
复制
Install-Package Swashbuckle.AspNetCore -Version 6.2.3

Startup.cs

代码语言:javascript
复制
public class Startup
{
    
    public void ConfigureServices(IServiceCollection services)
    {
        // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            services.AddEndpointsApiExplorer();
            services.AddSwaggerGen(options =>
            {
                // https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-6.0&tabs=visual-studio
                options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
                {
                    Version = "v1",
                    Title = "爱发电 Badge",
                    Description = "爱发电 Badge - 由 Afdian.Server 构建",
                    TermsOfService = new Uri("https://github.com/yiyungent/Afdian.Sdk"),
                    Contact = new Microsoft.OpenApi.Models.OpenApiContact
                    {
                        Name = "Contact",
                        Url = new Uri("https://github.com/yiyungent/Afdian.Sdk/issues")
                    },
                    License = new Microsoft.OpenApi.Models.OpenApiLicense
                    {
                        Name = "MIT License",
                        Url = new Uri("https://github.com/yiyungent/Afdian.Sdk/blob/main/LICENSE")
                    },
                    //Extensions = new Microsoft.OpenApi.Models.OpenApiExtensibleDictionary<string, string>() { }
                });

                var xmlFilename = $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml";
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
            });
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseSwagger();
        app.UseSwaggerUI();
        
        // Others
        app.UseRouting();
        app.UseCors();

        app.UseDefaultFiles();
        app.UseStaticFiles();

        app.UseAuthorization();
        // ...
    }
    
}
Swashbuckle.AspNetCore请求上的 Authorization

参考:

代码语言:javascript
复制
string bearerToken = Request.Headers["Authorization"];
代码语言:javascript
复制
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Info
    {
        Version = "v1",
        Title = "Employee Navigator",
        Description = "Authorization Key: Z29vZEtleQ==",
    });
    c.AddSecurityDefinition("Bearer", new ApiKeyScheme
    {
        Name = "Authorization",
        In = "header",
        Type = "apiKey",
        Description = "Authorization Key: Z29vZEtleQ=="
    });
    c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
    {
        { "Bearer", new[] { "readAccess", "writeAccess" } 
    });
    
});
多 API Version

参考:

补充

如何忽略一个接口 为 Controller 或者 Action 方法上添加特性标记 [ApiExplorerSettings(IgnoreApi =true)] 即可

.NET6 手动配置启动项地址

代码语言:javascript
复制
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.WebHost.ConfigureKestrel((context, options) =>
{
  options.Listen(IPAddress.Any, 5001, listenOptions =>
  {
    listenOptions.UseHttps();
  });
});
var app = builder.Build();

## Kestrel 请求体最大为 50MB

代码语言:javascript
复制
// 设置应用服务器Kestrel请求体最大为50MB 52428800
builder.WebHost.ConfigureKestrel(o => o.Limits.MaxRequestBodySize = null);

// 设置即重置文件上传的大小限制 
builder.Services.Configure<FormOptions>(o =>
{
    o.MultipartBodyLengthLimit = long.MaxValue;
});

参考

感谢帮助!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 依赖注入
  • AOP
  • ASP.NET Core 中的静态文件
  • 断点续传
  • WebSocket
  • 发布
  • 在 ASP.NET Core 中 启用跨域
    • 使用默认策略和中间件的 CORS
      • 预检请求 preflight-requests
        • 设置预检过期时间
        • 使用终结点路由和 [HttpOptions] 测试 CORS
    • Q&A
    • 补充
      • SSH
        • System.NullReferenceException: WebApi.Startup.ConfigureServices(IServiceCollection services)
          • MySql.Data.EntityFrameworkCore 8.0.22 仅与 Microsoft.EntityFrameworkCore 3.1 兼容
            • 插件系统
              • 合并dll
                • WPF 集成 ASP.NET Core
                  • WebView
                    • 进程管理
                      • HttpClient 上传文件
                        • 通过流式传输上传大型文件
                          • 解析 nuget 的 nupkg
                            • 自定义模板
                              • JavaScript 拦截请求
                                • 创建 nuget 源代码 、符号包
                                  • 创建符号包
                                  • 发布符号包
                                • WebTerm
                                  • 拦截方法
                                    • 下载文件
                                      • Web 在线代理
                                        • WebAPI 在线文档
                                          • Swashbuckle
                                        • .NET6 手动配置启动项地址
                                        • 参考
                                        相关产品与服务
                                        对象存储
                                        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                                        领券
                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档