网站首页 > 技术文章 正文
文件系统提供程序
使用ABP CLI安装
在项目的文件夹(.csproj文件)中打开命令行窗口输入以下命令:
abp add-package Volo.Abp.BlobStoring.FileSystem
手动安装
- 添加 Volo.Abp.BlobStoring.FileSystem NuGet包添加到你的项目:
Install-Package Volo.Abp.BlobStoring.FileSystem
- 添加 AbpBlobStoringFileSystemModule到你的模块的依赖列表:
[DependsOn(
//...other dependencies
typeof(AbpBlobStoringFileSystemModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
配置
配置是在模块类的 ConfigureServices 方法完成的.
示例: 配置为默认使用文件系统存储提供程序
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseFileSystem(fileSystem =>
{
fileSystem.BasePath = "C:\\my-files";
});
});
});
UseFileSystem 扩展方法用于为容器设置文件系统提供程序并配置文件系统选项.
选项
- BasePath (string): 存储BLOB的基本文件夹路径,它是必选的.
- AppendContainerNameToBasePath (bool; 默认: true): 指定是否在基本文件夹中创建具有容器名称的文件夹. 如果你在同一个 BaseFolder 中存储多个容器,请将其保留为true. 如果你不喜欢不必要的更深层次的文件夹,你可以将它设置为 false.
文件路径计算
文件系统提供程序在文件夹中组织BLOB文件并实现一些约定. 默认情况下,BLOB文件的完整路径由以下规则确定:
- 它以如上所述配置的 BasePath 开始.
- 如果当前租户为 null(或容器禁用多租户),则追加 host 文件夹.
- 如果当前租户不为 null,则追加 tenants/<tenant-id> 文件夹.
- 如果 AppendContainerNameToBasePath 为true,则追加容器的名称. 如果容器名称包含 /,将导致文件夹嵌套.
- 追加BLOB名称,如果BLOB名称包含 / 它创建文件夹. 如果BLOB名称包含 . 它将有一个文件扩展名.
扩展文件系统提供程序
- FileSystemBlobProvider 是实现文件系统存储的主要服务. 你可以从这个类继承并覆盖方法进行自定义.
- IBlobFilePathCalculator 服务用于计算文件路径. 默认实现是 DefaultBlobFilePathCalculator . 如果你想自定义文件路径计算,可以替换/覆盖它.
数据库提供程序
BLOB存储数据库提供程序可以将BLOB存储在关系或非关系数据库中.
有两个数据库提供程序实现;
- Volo.Abp.BlobStoring.Database.EntityFrameworkCore 包实现EF Core, 它可以通过EF Core存储BLOB在任何支持的DBMS中.
- Volo.Abp.BlobStoring.Database.MongoDB 包实现了MongoDB.
使用ABP CLI安装
在项目的文件夹(.csproj文件)中打开命令行窗口输入以下命令:
abp add-package Volo.Abp.BlobStoring.Database
手动安装
这里是此提供程序定义的所有包:
- Volo.Abp.BlobStoring.Database.Domain.Shared
- Volo.Abp.BlobStoring.Database.Domain
- Volo.Abp.BlobStoring.Database.EntityFrameworkCore
- Volo.Abp.BlobStoring.Database.MongoDB
你可以只安装 Volo.Abp.BlobStoring.Database.EntityFrameworkCore 或 Volo.Abp.BlobStoring.Database.MongoDB (根据你的偏好),因为它们依赖其他包.
安装完成后,添加 DepenedsOn 属性到相关模块.下面是由上面列出的相关NuGet包定义的模块类列表:
- BlobStoringDatabaseDomainModule
- BlobStoringDatabaseDomainSharedModule
- BlobStoringDatabaseEntityFrameworkCoreModule
- BlobStoringDatabaseMongoDbModule
如果你正在使用EF Core,还需要配置你的Migration DbContext将BLOB存储表添加到你的数据库. 在 OnModelCreating 方法中调用 builder.ConfigureBlobStoring() 扩展方法来包含到DbContext的映射. 你可以使用标准的 Add-Migration 和 Update-Database 命令在数据库中创建必要的表.
配置
连接字符串
如果你要使用你的 Default 连接字符串,则不需要做任何其他配置.
如果要将BLOB存储到单独的数据库,请在配置文件(appsettings.json)中将 AbpBlobStoring 用作连接字符串名称.
配置容器
如果只使用数据库存储提供程序,则不需要手动配置,因为它是自动完成的. 如果使用多个存储提供程序,可能需要对其进行配置.
如同BLOB存储文档所述,配置是在模块类的 ConfigureServices 方法完成的.
示例: 配置为默认使用数据库系统存储提供程序
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseDatabase();
});
});
附加信息
如需要使用BLOB存储服务处理数据库表/实体,可以使用以下信息.
实体
此模块定义的实体:
- DatabaseBlobContainer (aggregate root) 表示存储在数据库中的容器.
- DatabaseBlob (aggregate root) 表示数据库中的BLOB.
仓储
- IDatabaseBlobContainerRepository
- IDatabaseBlobRepository
你还可以使用 IRepository 和 IRepository 来获得 IQueryable 能力.
其他服务
- DatabaseBlobProvider 是实现数据库BLOB存储提供程序的主要服务,如果你想要通过依赖注入覆盖/替换它(不要替换 IBlobProvider 接口,而是替换 DatabaseBlobProvider 类).
Azure提供程序
BLOB存储Azure提供程序可以将BLOB存储在Azure Blob storage中.
使用ABP CLI安装
在项目的文件夹(.csproj文件)中打开命令行窗口输入以下命令:
abp add-package Volo.Abp.BlobStoring.Azure
手动安装
- 添加 Volo.Abp.BlobStoring.Azure NuGet包添加到你的项目:
Install-Package Volo.Abp.BlobStoring.Azure
- 添加 AbpBlobStoringAzureModule到你的模块的依赖列表:
[DependsOn(
//...other dependencies
typeof(AbpBlobStoringAzureModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
配置
配置是在模块类的 ConfigureServices 方法完成的.
示例: 配置为默认使用Azure存储提供程序
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseAzure(azure =>
{
azure.ConnectionString = "your azure connection string";
azure.ContainerName = "your azure container name";
azure.CreateContainerIfNotExists = false;
});
});
});
选项
- ConnectionString (string): 连接字符串包括应用程序在运行时使用共享密钥授权访问Azure存储帐户中的数据所需的授权信息.
- ContainerName (string): 你可以在azure中指定容器名称. 如果没有指定它将使用 BlogContainerName 属性定义的BLOB容器的名称. 请注意Azure有一些命名容器的规则,容器名称必须是有效的DNS名称,符合以下命名规则:容器名称必须以字母或数字开头或结尾,并且只能包含字母,数字和破折号(-)字符.每个破折号(-)必须紧跟在字母或数字之后;容器名称中不允许使用连续的破折号.容器名称中的所有字母都必须小写.容器名称的长度必须在3到63个字符之间.
- CreateContainerIfNotExists (bool): 默认值为 false, 如果azure中不存在容器, AzureBlobProvider 将尝试创建它.
Azure BLOB 名称计算器
Azure BLOB提供程序组织BLOB名称并实现一些约定. 默认情况下BLOB的全名由以下规则确定:
- 如果当前租户为 null(或容器禁用多租户),则追加 host 字符串.
- 如果当前租户不为 null,则追加 tenants/<tenant-id> 字符串.
- 追加 BLOB 名称.
其他服务
- AzureBlobProvider 是实现Azure BLOB存储提供程序的主要服务,如果你想要通过依赖注入覆盖/替换它(不要替换 IBlobProvider 接口,而是替换 AzureBlobProvider 类).
- IAzureBlobNameCalculator 服务用于计算文件路径. 默认实现是 DefaultAzureBlobNameCalculator . 如果你想自定义文件路径计算,可以替换/覆盖它.
Aliyun提供程序
BLOB存储Aliyun提供程序可以将BLOB存储在Aliyun Blob storage中.
使用ABP CLI安装
在项目的文件夹(.csproj文件)中打开命令行窗口输入以下命令:
abp add-package Volo.Abp.BlobStoring.Aliyun
手动安装
- 添加 Volo.Abp.BlobStoring.Aliyun NuGet包添加到你的项目:
Install-Package Volo.Abp.BlobStoring.Aliyun
- 添加 AbpBlobStoringAliyunModule到你的模块的依赖列表:
[DependsOn(
//...other dependencies
typeof(AbpBlobStoringAliyunModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
配置
配置是在模块类的 ConfigureServices 方法完成的.
示例: 配置为默认使用Aliyun存储提供程序
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseAliyun(aliyun =>
{
aliyun.AccessKeyId = "your aliyun access key id";
aliyun.AccessKeySecret = "your aliyun access key secret";
aliyun.Endpoint = "your oss endpoint";
aliyun.RegionId = "your sts region id";
aliyun.RoleArn = "the arn of ram role";
aliyun.RoleSessionName = "the name of the certificate";
aliyun.Policy = "policy";
aliyun.DurationSeconds = "expiration date";
aliyun.ContainerName = "your aliyun container name";
aliyun.CreateContainerIfNotExists = false;
});
});
});
选项
- AccessKeyId ([NotNull]string): 云账号AccessKey是访问阿里云API的密钥,具有该账户完全的权限,请你务必妥善保管!强烈建议遵循阿里云安全最佳实践,使用RAM子用户AccessKey来进行API调用.
- AccessKeySecret ([NotNull]string): 同上.
- Endpoint ([NotNull]string): Endpoint表示OSS对外服务的访问域名. 访问域名和数据中心
- UseSecurityTokenService (bool): 是否使用STS临时授权访问OSS,默认false. STS临时授权访问OSS
- RegionId (string): STS服务的接入地址,每个地址的功能都相同,请尽量在同地域进行调用. 接入地址
- RoleArn ([NotNull]string): STS所需角色ARN.
- RoleSessionName ([NotNull]string): 用来标识临时访问凭证的名称,建议使用不同的应用程序用户来区分.
- Policy (string): 在扮演角色的时候额外添加的权限限制. 请参见基于RAM Policy的权限控制.
- DurationSeconds (int): 设置临时访问凭证的有效期,单位是s,最小为900,最大为3600.
- ContainerName (string): 你可以在aliyun中指定容器名称. 如果没有指定它将使用 BlogContainerName 属性定义的BLOB容器的名称(请参阅BLOB存储文档). 请注意Aliyun有一些命名容器的规则,容器名称必须是有效的DNS名称,符合以下命名规则:只能包含小写字母,数字和短横线(-)必须以小写字母和数字开头和结尾Bucket名称的长度限制在3到63个字符之间
- CreateContainerIfNotExists (bool): 默认值为 false, 如果aliyun中不存在容器, AliyunBlobProvider 将尝试创建它.
- TemporaryCredentialsCacheKey (bool): STS凭证缓存Key,默认Guid.NewGuid().ToString("N").
Aliyun BLOB 名称计算器
Aliyun BLOB提供程序组织BLOB名称并实现一些约定. 默认情况下BLOB的全名由以下规则确定:
- 如果当前租户为 null(或容器禁用多租户 ),则追加 host 字符串.
- 如果当前租户不为 null,则追加 tenants/<tenant-id> 字符串.
- 追加 BLOB 名称.
其他服务
- AliyunBlobProvider 是实现Aliyun BLOB存储提供程序的主要服务,如果你想要通过依赖注入覆盖/替换它(不要替换 IBlobProvider 接口,而是替换 AliyunBlobProvider 类).
- IAliyunBlobNameCalculator 服务用于计算文件路径. 默认实现是 DefaultAliyunBlobNameCalculator. 如果你想自定义文件路径计算,可以替换/覆盖它.
- IOssClientFactory 服务用于生成OSS客户端. 默认实现是 DefaultOssClientFactory . 如果你想自定义OSS客户端生成,可以替换/覆盖它.
Minio 提供程序
BLOB Storing Minio提供程序帮助你存储对象到 MinIO Object storage
使用ABP CLI安装
在项目的文件夹(.csproj文件)中打开命令行窗口输入以下命令:
abp add-package Volo.Abp.BlobStoring.Minio
手动安装
- 添加 Volo.Abp.BlobStoring.Minio NuGet包添加到你的项目:
Install-Package Volo.Abp.BlobStoring.Minio
- 添加 AbpBlobStoringMinioModule到你的模块的依赖列表:
[DependsOn(
//...other dependencies
typeof(AbpBlobStoringMinioModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
配置
配置是在模块类的 ConfigureServices 方法完成的.
示例: 配置为默认使用Minio存储提供程序
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseMinio(minio =>
{
minio.EndPoint = "你的 minio endPoint";
minio.AccessKey = "你的 minio accessKey";
minio.SecretKey = "你的 minio secretKey";
minio.BucketName = "你的 minio bucketName";
});
});
});
选项
- EndPoint (string): 你的Minio对象存储服务的URL
- AccessKey (string): Access key是唯一标识你的账户的用户ID,
- SecretKey (string): Access key是唯一标识你的账户的用户ID
- BucketName (string):你可以指定bucket名称,如果没有指定,将使用 BlogContainerName 属性定义的BLOB容器的名称,MinIO完全兼容S3标准,所以有一些 bucket命名规则,必须符合规则:Bucket名称必须介于 3 到 63 个字符之间.Bucket名称只能由小写字母、数字、句点 (.) 和连字符 (-) 组成.Bucket名称必须以字母或数字开头和结尾.Bucket名称不能是ip (例如, 192.168.5.4).Bucket名称不能以 xn-- 开头, (对于2020年2月以后创建的 Bucket).Bucket名称在分区中必须唯一 .Bucket 与 Amazon S3 Transfer Acceleration 一起使用时名称中不能有句点 (.).
- WithSSL (bool): 默认 false,代表使用HTTPS,
- CreateContainerIfNotExists (bool): 默认 false,如果不存在bucket, MinioBlobProvider 将会创建一个,
Minio BLOB 名称计算器
默认情况下BLOB的全名由以下规则确定:
- 如果当前租户为 null(或容器禁用多租户),则追加 host 字符串,
- 如果当前租户不为 null,则追加 tenants/<tenant-id> 字符串,
- 追加 BLOB 名称,
其他服务
- MinioBlobProvider 是实现Minio BLOB存储提供程序的主要服务,如果你想要通过依赖注入覆盖/替换它(不要替换 IBlobProvider 接口,而是替换 MinioBlobProvider 类).
- IMinioBlobNameCalculator 服务用于计算文件路径. 默认实现是 DefaultMinioBlobNameCalculator. 如果你想自定义文件路径计算,可以替换/覆盖它.
Aws提供程序
BLOB存储Aws提供程序可以将BLOB存储在Amazon Simple Storage Service中.
使用ABP CLI安装
在项目的文件夹(.csproj文件)中打开命令行窗口输入以下命令:
abp add-package Volo.Abp.BlobStoring.Aws
手动安装
- 添加 Volo.Abp.BlobStoring.Aws NuGet包添加到你的项目:
Install-Package Volo.Abp.BlobStoring.Aws
- 添加 AbpBlobStoringAwsModule到你的模块的依赖列表:
[DependsOn(
//...other dependencies
typeof(AbpBlobStoringAwsModule) //Add the new module dependency
)]
public class YourModule : AbpModule
{
}
配置
配置是在模块类的 ConfigureServices 方法完成的.
示例: 配置为默认使用Aws存储提供程序
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseAws(Aws =>
{
Aws.AccessKeyId = "your Aws access key id";
Aws.SecretAccessKey = "your Aws access key secret";
Aws.UseCredentials = "set true to use credentials";
Aws.UseTemporaryCredentials = "set true to use temporary credentials";
Aws.UseTemporaryFederatedCredentials = "set true to use temporary federated credentials";
Aws.ProfileName = "the name of the profile to get credentials from";
Aws.ProfilesLocation = "the path to the aws credentials file to look at";
Aws.Region = "the system name of the service";
Aws.Name = "the name of the federated user";
Aws.Policy = "policy";
Aws.DurationSeconds = "expiration date";
Aws.ContainerName = "your Aws container name";
Aws.CreateContainerIfNotExists = false;
});
});
});
选项
- AccessKeyId (string): AWS Access Key ID.
- SecretAccessKey (string): AWS Secret Access Key.
- UseCredentials (bool): 使用本地凭证访问AWS服务,默认: false.
- UseTemporaryCredentials (bool): 使用临时凭证访问AWS服务,默认: false.
- UseTemporaryFederatedCredentials (bool): 使用联合身份用户临时凭证访问AWS服务, 默认: false.
- ProfileName (string): 本地凭证配置文件名称.
- ProfilesLocation (string): 本地配置文件位置.
- Region (string): 服务的地区名称.
- Policy (string): JSON格式的IAM策略.
- DurationSeconds (int): 设置临时访问凭证的有效期,单位是s,最小为900,最大为129600.
- ContainerName (string): 你可以在Aws中指定容器名称. 如果没有指定它将使用 BlogContainerName 属性定义的BLOB容器的名称(请参阅BLOB存储文档). 请注意Aws有一些命名容器的规则,容器名称必须是有效的DNS名称,符合以下命名规则:Bucket名称必须介于 3 到 63 个字符之间.Bucket名称只能由小写字母、数字、句点 (.) 和连字符 (-) 组成.Bucket名称必须以字母或数字开头和结尾.Bucket名称不能是ip (例如, 192.168.5.4).Bucket名称不能以 xn-- 开头, (对于2020年2月以后创建的 Bucket).Bucket名称在分区中必须唯一 .Bucket 与 Amazon S3 Transfer Acceleration 一起使用时名称中不能有句点 (.).
- CreateContainerIfNotExists (bool): 默认值为 false, 如果Aws中不存在容器, AwsBlobProvider 将尝试创建它.
Aws BLOB 名称计算器
Aws BLOB提供程序组织BLOB名称并实现一些约定. 默认情况下BLOB的全名由以下规则确定:
- 如果当前租户为 null(或容器禁用多租户),则追加 host 字符串.
- 如果当前租户不为 null,则追加 tenants/<tenant-id> 字符串.
- 追加 BLOB 名称.
其他服务
- AwsBlobProvider 是实现Aws BLOB存储提供程序的主要服务,如果你想要通过依赖注入覆盖/替换它(不要替换 IBlobProvider 接口,而是替换 AwsBlobProvider 类).
- IAwsBlobNameCalculator 服务用于计算文件路径. 默认实现是 DefaultAwsBlobNameCalculator. 如果你想自定义文件路径计算,可以替换/覆盖它.
- IAmazonS3ClientFactory 服务用于生成AWS S3客户端. 默认实现是 DefaultAmazonS3ClientFactory . 如果你想自定义AWS S3客户端生成,可以替换/覆盖它.
创建自定义提供程序
本文档通过一个示例说明如何为BLOB存储系统创建新的存储提供程序.
示例实现
第一步是创建一个实现 IBlobProvider 接口或 BlobProviderBase 抽象类继承的类.
using System.IO;
using System.Threading.Tasks;
using Volo.Abp.BlobStoring;
using Volo.Abp.DependencyInjection;
namespace AbpDemo
{
public class MyCustomBlobProvider : BlobProviderBase, ITransientDependency
{
public override Task SaveAsync(BlobProviderSaveArgs args)
{
//TODO...
}
public override Task<bool> DeleteAsync(BlobProviderDeleteArgs args)
{
//TODO...
}
public override Task<bool> ExistsAsync(BlobProviderExistsArgs args)
{
//TODO...
}
public override Task<Stream> GetOrNullAsync(BlobProviderGetArgs args)
{
//TODO...
}
}
}
- MyCustomBlobProvider 继承 BlobProviderBase 并覆盖 abstract 方法. 实际的实现取决于开发者.
- 实现 ITransientDependency 接口将这个类注做为瞬态服务注册到依赖注入系统.
注意: 命名约定很重要. 如果类名没有以 BlobProvider 结尾,则必须手动注册/公开你的服务为 IBlobProvider.
现在你可以配置容器(在模块的 ConfigureServices 方法中)使用 MyCustomBlobProvider 类:
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.ProviderType = typeof(MyCustomBlobProvider);
});
});
BlobContainerConfiguration 扩展方法
如果你想提供一个更简单的配置方式,可以为 BlobContainerConfiguration 类创建一个扩展方法:
public static class MyBlobContainerConfigurationExtensions
{
public static BlobContainerConfiguration UseMyCustomBlobProvider(
this BlobContainerConfiguration containerConfiguration)
{
containerConfiguration.ProviderType = typeof(MyCustomBlobProvider);
return containerConfiguration;
}
}
然后使用扩展方法更容易地配置容器:
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseMyCustomBlobProvider();
});
});
额外的配置选项
BlobContainerConfiguration 允许添加/删除提供程序特定的配置对象. 如果你的提供者需要额外的配置,你可以为 BlobContainerConfiguration 创建一个包装类提供的类型安全配置选项:
public class MyCustomBlobProviderConfiguration
{
public string MyOption1
{
get => _containerConfiguration
.GetConfiguration<string>("MyCustomBlobProvider.MyOption1");
set => _containerConfiguration
.SetConfiguration("MyCustomBlobProvider.MyOption1", value);
}
private readonly BlobContainerConfiguration _containerConfiguration;
public MyCustomBlobProviderConfiguration(
BlobContainerConfiguration containerConfiguration)
{
_containerConfiguration = containerConfiguration;
}
}
然后可以这样更改 MyBlobContainerConfigurationExtensions 类:
public static class MyBlobContainerConfigurationExtensions
{
public static BlobContainerConfiguration UseMyCustomBlobProvider(
this BlobContainerConfiguration containerConfiguration,
Action<MyCustomBlobProviderConfiguration> configureAction)
{
containerConfiguration.ProviderType = typeof(MyCustomBlobProvider);
configureAction.Invoke(
new MyCustomBlobProviderConfiguration(containerConfiguration)
);
return containerConfiguration;
}
public static MyCustomBlobProviderConfiguration GetMyCustomBlobProviderConfiguration(
this BlobContainerConfiguration containerConfiguration)
{
return new MyCustomBlobProviderConfiguration(containerConfiguration);
}
}
- 向 UseMyCustomBlobProvider 方法添加了一个参数,允许开发人员设置其他选项.
- 添加了一个新的 GetMyCustomBlobProviderConfiguration 方法,该方法将在 MyCustomBlobProvider 类内使用获取配置的值.
如下设置 MyOption1:
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseMyCustomBlobProvider(provider =>
{
provider.MyOption1 = "my value";
});
});
});
最后可以使用 GetMyCustomBlobProviderConfiguration 方法访问额外的选项:
public class MyCustomBlobProvider : BlobProviderBase, ITransientDependency
{
public override Task SaveAsync(BlobProviderSaveArgs args)
{
var config = args.Configuration.GetMyCustomBlobProviderConfiguration();
var value = config.MyOption1;
//...
}
}
- 上一篇: Blob文件下载方式
- 下一篇: Blob(Binary Large Object)
猜你喜欢
- 2024-11-20 抖音 Android 性能优化系列:启动优化实践
- 2024-11-20 Restic设计原理
- 2024-11-20 前端必读榜——如何在JavaScript中用SpreadJS导入/导出Excel文件
- 2024-11-20 Axios API详细介绍及使用
- 2024-11-20 镜像仓库registry命令行启动,垃圾回收和服务监听我全都要
- 2024-11-20 ElasticSearch知识day04
- 2024-11-20 详解Oracle 11g如何快速定位到lobsegment、lobindex对应的表
- 2024-11-20 前端必读:如何在 JavaScript 中使用SpreadJS导入和导出 Excel 文件
- 2024-11-20 前端文件下载的几种方式
- 2024-11-20 JavaScript奇淫技巧:20行代码,实现屏幕录像
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-