# 亚马逊 S3 提供商

> Source: https://strapi.nodejs.cn/cms/configurations/media-library-providers/amazon-s3

🌐 Amazon S3 provider

`@strapi/provider-upload-aws-s3` 包允许你将媒体库资源存储在 Amazon S3 或任何兼容 S3 的服务上（如 Cloudflare R2、Scaleway、MinIO 等）。本页面涵盖了提供商配置、必要的 AWS 设置（IAM、CORS、中间件）以及扩展选项，如加密、校验和以及用于私有存储桶的签名 URL。

🌐 The `@strapi/provider-upload-aws-s3` package lets you store Media Library assets on Amazon S3 or any S3-compatible service (Cloudflare R2, Scaleway, MinIO, etc.). This page covers provider configuration, required AWS setup (IAM, CORS, middleware), and extended options such as encryption, checksums, and signed URLs for private buckets.

[媒体库](/cms/features/media-library) 功能由一个名为 Upload 的后端服务器包提供支持，该包利用了提供程序的使用。

🌐 The [Media Library](/cms/features/media-library) feature is powered by a back-end server package called Upload which leverages the use of providers.

Strapi 为媒体库维护了 3 个提供者。本页面关于 Amazon S3 提供者的安装和配置。有关其他提供者，请参阅 [媒体库页面](/cms/features/media-library#providers) 中的列表。

🌐 Strapi maintains 3 providers for the Media Library. The present page is about the Amazon S3 provider installation and configuration. For other providers, please refer to the list in the [Media Library page](/cms/features/media-library#providers).

## 安装 {#installation}

🌐 Installation

要安装官方 Strapi 维护的 AWS S3 提供程序，请在终端中运行以下命令：

🌐 To install the official Strapi-maintained AWS S3 provider, run the following command in a terminal:

```bash
yarn add @strapi/provider-upload-aws-s3
```

```bash
npm install @strapi/provider-upload-aws-s3 --save
```

## 配置 {#configuration}

🌐 Configuration

提供程序配置在 [“/config/plugins” 文件](/cms/configurations/plugins) 中定义。如果该文件不存在，请先创建它。使用每个环境不同的提供程序时，请在 `/config/env/${yourEnvironment}/plugins.js|ts` 中指定正确的配置（参见 [环境](/cms/configurations/environment)）。

🌐 Providers configuration is defined in [the `/config/plugins` file](/cms/configurations/plugins). If this file does not exist, create it first. When using a different provider per environment, specify the correct configuration in `/config/env/${yourEnvironment}/plugins.js|ts` (see [environments](/cms/configurations/environment)).

提供者配置接受以下条目：

🌐 The provider configuration accepts the following entries:

* `provider` 用于定义提供者名称（即 `amazon-s3`）
* `providerOptions` 用于定义在提供者构建过程中传递的选项（完整的选项列表请参见 [AWS documentation](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property) ；在专门的[扩展提供者选项部分](#extended-provider-options)中给出了一些示例）
* `actionOptions` 用于定义直接传递给每个方法各自参数的选项。官方 AWS 文档列出了  [upload/uploadStream](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property)  和  [delete](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObject-property) 可用的选项。

### 基本示例 {#basic-example}

🌐 Basic example

```js title="/config/plugins.js"
module.exports = ({ env }) => ({
  // ...
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        baseUrl: env('CDN_URL'),
        rootPath: env('CDN_ROOT_PATH'),
        s3Options: {
          credentials: {
            accessKeyId: env('AWS_ACCESS_KEY_ID'),
            secretAccessKey: env('AWS_ACCESS_SECRET'),
          },
          region: env('AWS_REGION'),
          params: {
            ACL: env('AWS_ACL', 'public-read'),
            signedUrlExpires: env('AWS_SIGNED_URL_EXPIRES', 15 * 60),
            Bucket: env('AWS_BUCKET'),
          },
        },
      },
      actionOptions: {
        upload: {},
        uploadStream: {},
        delete: {},
      },
    },
  },
  // ...
});
```

```ts title="/config/plugins.ts"

  // ...
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        baseUrl: env('CDN_URL'),
        rootPath: env('CDN_ROOT_PATH'),
        s3Options: {
          credentials: {
            accessKeyId: env('AWS_ACCESS_KEY_ID'),
            secretAccessKey: env('AWS_ACCESS_SECRET'),
          },
          region: env('AWS_REGION'),
          params: {
            ACL: env('AWS_ACL', 'public-read'),
            signedUrlExpires: env('AWS_SIGNED_URL_EXPIRES', 15 * 60),
            Bucket: env('AWS_BUCKET'),
          },
        },
      },
      actionOptions: {
        upload: {},
        uploadStream: {},
        delete: {},
      },
    },
  },
  // ...
});
```

如果你将存储桶用作 CDN 并在自定义域上交付内容，你可以使用 `baseUrl` 和 `rootPath` 属性。使用环境配置来定义你的资源 URL 将如何保存在 Strapi 中。

🌐 If you use the bucket as a CDN and deliver the content on a custom domain, you can use the `baseUrl` and `rootPath` properties. Use environment configurations to define how your asset URLs will be saved inside Strapi.

:::info AWS SDK V3 URL format

该提供者使用 AWS SDK V3，它默认对 S3 URL 使用  [virtual-hosted-style URIs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#virtual-hosted-style-access) 。如果要改为使用路径式 URL，请显式设置 `baseUrl`：

```js
baseUrl: `https://s3.${process.env.AWS_REGION}.amazonaws.com/${process.env.AWS_BUCKET}`,
```

:::

:::caution Deprecated root-level credential format

较早的 Strapi 指南和博客文章显示 `accessKeyId` 和 `secretAccessKey` 直接放在 `s3Options` 中。这个根级别的格式仍然有效，但会触发弃用警告。请改为在 `credentials` 对象中传递凭证（如上面的示例所示）。

🌐 Older Strapi guides and blog posts show `accessKeyId` and `secretAccessKey` placed directly in `s3Options`. This root-level format still works but triggers a deprecation warning. Pass credentials inside a `credentials` object instead (as shown in the examples above).

:::

:::info AWS credential provider functions

你可以将 AWS 凭证提供程序函数（例如来自 `@aws-sdk/credential-providers`）传递给 `s3Options.credentials`，而不是静态的 `credentials` 对象。这允许在运行时解析和刷新凭证，而无需重启进程，这在应用生命周期内凭证发生变化时非常有用（例如临时凭证、凭证轮换）：

🌐 Instead of a static `credentials` object, you can pass an AWS credential provider function (e.g., from `@aws-sdk/credential-providers`) to `s3Options.credentials`. This allows credentials to be resolved and refreshed at runtime without restarting the process, which is useful when credentials change during application lifetime (e.g., temporary credentials, credential rotation):

```ts title="/config/plugins.ts"

  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        s3Options: {
          credentials: fromNodeProviderChain(), // AWS SDK resolves credentials dynamically
          region: env('AWS_REGION'),
          params: {
            Bucket: env('AWS_BUCKET'),
          },
        },
      },
    },
  },
});
```

提供者函数必须返回一个承诺，该承诺解析为具有 `accessKeyId` 和 `secretAccessKey` 属性的凭据。

🌐 The provider function must return a promise that resolves to credentials with `accessKeyId` and `secretAccessKey` properties.

:::

:::caution

为了确保提供者正常工作，你还需要配置 IAM 权限、存储桶 CORS 以及 Strapi 安全中间件（参见 [必要设置](#required-setup)）。

🌐 To ensure the provider works correctly, you also need to configure IAM permissions, bucket CORS, and the Strapi security middleware (see [Required setup](#required-setup)).

:::

### 私有存储桶和签名 URL {#private-bucket-and-signed-urls}

🌐 Private bucket and signed URLs

如果你的存储桶配置为私有，请在 `params` 对象中将 `ACL` 选项设置为 `private`。这可以确保文件的 URL 是签名的。

🌐 If your bucket is configured to be private, set the `ACL` option to `private` in the `params` object. This ensures file URLs are signed.

你可以通过在 `params` 对象中设置 `signedUrlExpires` 选项来定义签名 URL 的过期时间。默认值是 15 分钟。

🌐 You can define the expiration time of the signed URL by setting the `signedUrlExpires` option in the `params` object. The default value is 15 minutes.

:::note

如果你正在使用 CDN，URL 将不会被签名。

🌐 If you are using a CDN, the URLs will not be signed.

:::

```js title="/config/plugins.js" {13-17}
module.exports = ({ env }) => ({
  // ...
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        s3Options: {
          credentials: {
            accessKeyId: env('AWS_ACCESS_KEY_ID'),
            secretAccessKey: env('AWS_ACCESS_SECRET'),
          },
          region: env('AWS_REGION'),
          params: {
            ACL: 'private', // <== set ACL to private
            signedUrlExpires: env('AWS_SIGNED_URL_EXPIRES', 15 * 60),
            Bucket: env('AWS_BUCKET'),
          },
        },
      },
      actionOptions: {
        upload: {},
        uploadStream: {},
        delete: {},
      },
    },
  },
  // ...
});
```

## 所需设置 {#required-setup}

🌐 Required setup

以下是为了让你的 AWS S3 设置能够与媒体库配合使用，需要考虑的最低配置操作。

🌐 The following are the minimum configuration actions to take into account for your AWS S3 setup to work with the Media Library.

### IAM 策略操作 {#iam-policy-actions}

🌐 IAM policy actions

以下是 AWS S3 提供程序工作所需的最低权限：

🌐 The following are the minimum amount of permissions needed for the AWS S3 provider to work:

```json
"Action": [
  "s3:PutObject",
  "s3:GetObject",
  "s3:ListBucket",
  "s3:DeleteObject",
  "s3:PutObjectAcl"
],
```

### 存储桶 CORS 配置 {#bucket-cors-configuration}

🌐 Bucket CORS configuration

要显示上传到 S3 的 GIF 和视频的缩略图，请编辑你的存储桶的 CORS 配置，以便在 Strapi 中正确显示缩略图。操作方法如下：

🌐 To display thumbnails for GIFs and videos uploaded to S3, edit your bucket's CORS configuration so that thumbnails are properly shown in Strapi. To do so:

1. 在 AWS 控制台中打开你的存储桶。
2. 导航到 _权限_ 选项卡。
3. 找到 _跨域资源共享 (CORS)_ 字段。
4. 添加以下 CORS 策略（或根据你的需要进行调整）:

```json
[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET"],
    "AllowedOrigins": ["YOUR STRAPI URL"],
    "ExposeHeaders": [],
    "MaxAgeSeconds": 3000
  }
]
```

### 安全中间件配置 {#security-middleware-configuration}

🌐 Security middleware configuration

默认的 Strapi 安全中间件设置会阻止媒体库中的 S3 缩略图预览。修改 `contentSecurityPolicy` 设置以允许从你的 S3 存储桶加载媒体。将 `strapi::security` 字符串替换为以下对象（详情请参见 [中间件配置](/cms/configurations/middlewares#security)）：

🌐 The default Strapi security middleware settings block S3 thumbnail previews in the Media Library. Modify the `contentSecurityPolicy` settings to allow loading media from your S3 bucket. Replace the `strapi::security` string with the following object (see [middleware configuration](/cms/configurations/middlewares#security) for details):

```js title="/config/middlewares.js"
module.exports = [
  // ...
  {
    name: 'strapi::security',
    config: {
      // highlight-start
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          'connect-src': ["'self'", 'https:'],
          'img-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'yourBucketName.s3.yourRegion.amazonaws.com',
          ],
          'media-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'yourBucketName.s3.yourRegion.amazonaws.com',
          ],
          upgradeInsecureRequests: null,
        },
      },
      // highlight-end
    },
  },
  // ...
];
```

如果你的存储桶名称包含点，并且 `forcePathStyle` 是 `false`，S3 会使用目录式 URL，例如在：

🌐 If your bucket name contains dots and `forcePathStyle` is `false`, S3 uses directory-style URLs, such as in:

`s3.yourRegion.amazonaws.com/your.bucket.name/image.jpg`

在这种情况下，对于 `img-src` 和 `media-src` 指令，请使用 `s3.yourRegion.amazonaws.com`（不带桶名称）。

🌐 In this case, use `s3.yourRegion.amazonaws.com` (without the bucket name) for the `img-src` and `media-src` directives.

## 与S3兼容的服务 {#s3-compatible-services}

🌐 S3-compatible services

AWS S3 提供程序通过使用 `endpoint` 选项与 S3 兼容服务配合工作。当 S3 兼容提供程序在其上传响应中返回有效的 URL 时，提供程序会原样信任该 URL，保持提供程序的正确格式（虚拟主机或路径样式）。对于在多部分上传响应中返回格式错误 URL 的提供程序（例如 IONOS、某些 MinIO 配置），提供程序会回退到从 `endpoint` 配置构建 URL。

🌐 The AWS S3 provider works with S3-compatible services by using the `endpoint` option. When an S3-compatible provider returns a valid URL in its upload response, the provider trusts that URL as-is, preserving the correct format (virtual-hosted or path-style) for the provider. For providers that return malformed URLs in multipart upload responses (e.g., IONOS, some MinIO configurations), the provider falls back to constructing the URL from the `endpoint` configuration.

有些提供商在 `s3Options` 中要求 `forcePathStyle: true`。当提供商不支持虚拟主机样式的 URL（例如 `bucket.endpoint.com`）而是使用路径样式的 URL（例如 `endpoint.com/bucket`）时，需要此选项。

🌐 Some providers require `forcePathStyle: true` in the `s3Options`. This option is needed when the provider does not support virtual-hosted-style URLs (e.g., `bucket.endpoint.com`), and instead uses path-style URLs (e.g., `endpoint.com/bucket`).

下表显示了每个提供者的兼容性设置：

🌐 The following table shows compatibility settings for each provider:

| 提供商 | `forcePathStyle` | `ACL` | 备注 |
| --- | --- | --- | --- |
| IONOS | `true` | 支持 | 通过端点回退自动修复格式错误的多部分 `Location` |
| MinIO | `true` | 支持 | 某些配置可能返回格式错误的 `Location`；通过端点回退自动修复 |
| Contabo | `true` | 支持 | - |
| Hetzner | `true` | 支持 | - |
| DigitalOcean Spaces | 不需要 | 支持 | 返回正确的虚拟主机 URL |
| Wasabi | 不需要 | 支持 | - |
| Scaleway | 不需要 | 支持 | 返回正确的虚拟主机 URL |
| Vultr | 不需要 | 支持 | - |
| Backblaze B2 | 不需要 | 支持 | 返回正确的虚拟主机 URL |
| Cloudflare R2 | 不需要 | 不支持 | 从参数中省略 `ACL` |

### Scaleway

```js title="/config/plugins.js"
module.exports = ({ env }) => ({
  // ...
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        // highlight-start
        s3Options: {
          credentials: {
            accessKeyId: env('SCALEWAY_ACCESS_KEY_ID'),
            secretAccessKey: env('SCALEWAY_ACCESS_SECRET'),
          },
          region: env('SCALEWAY_REGION'), // e.g "fr-par"
          endpoint: env('SCALEWAY_ENDPOINT'), // e.g. "https://s3.fr-par.scw.cloud"
          params: {
            Bucket: env('SCALEWAY_BUCKET'),
          },
        },
        // highlight-end
      },
    },
  },
  // ...
});
```

### IONOS / MinIO / Contabo

这些提供商需要 `forcePathStyle: true`，因为它们使用路径风格的 URL 而不是虚拟主机风格的 URL。

🌐 These providers require `forcePathStyle: true` because they use path-style URLs instead of virtual-hosted-style URLs.

```js title="/config/plugins.js"
module.exports = ({ env }) => ({
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        // highlight-start
        s3Options: {
          credentials: {
            accessKeyId: env('S3_ACCESS_KEY_ID'),
            secretAccessKey: env('S3_ACCESS_SECRET'),
          },
          region: env('S3_REGION'),
          endpoint: env('S3_ENDPOINT'),
          forcePathStyle: true, // Required for these providers
          params: {
            Bucket: env('S3_BUCKET'),
          },
        },
        // highlight-end
      },
    },
  },
});
```

### Cloudflare R2

Cloudflare R2 不支持 ACL。

🌐 Cloudflare R2 does not support ACLs.

```js title="/config/plugins.js"
module.exports = ({ env }) => ({
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        // highlight-start
        s3Options: {
          credentials: {
            accessKeyId: env('R2_ACCESS_KEY_ID'),
            secretAccessKey: env('R2_ACCESS_SECRET'),
          },
          region: 'auto',
          endpoint: env('R2_ENDPOINT'), // e.g. "https://<account-id>.r2.cloudflarestorage.com"
          params: {
            Bucket: env('R2_BUCKET'),
            // Do NOT set ACL - R2 does not support ACLs
          },
        },
        // highlight-end
      },
    },
  },
});
```

## 扩展提供者选项 {#extended-provider-options}

🌐 Extended provider options

`providerOptions` 中的 `providerConfig` 选项提供了用于数据完整性、安全性和成本优化的额外功能。

🌐 The `providerConfig` option inside `providerOptions` provides additional features for data integrity, security, and cost optimization.

为静态数据启用[服务器端加密](#server-side-encryption)
  为上传完整性启用[校验和验证](#checksum-validation)
  启用[条件写入](#conditional-writes-prevent-overwrites)以防止竞争条件
  对敏感内容使用带[签名 URL](#private-bucket-and-signed-urls) 的`ACL: 'private'`
  启用 [S3 bucket versioning](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html) 以便从意外删除中恢复

### 校验和验证 {#checksum-validation}

🌐 Checksum validation

启用自动校验和计算以确保上传期间的数据完整性。SDK 在客户端计算校验和，S3 在服务器端验证校验和。

🌐 Enable automatic checksum calculation to ensure data integrity during uploads. The SDK calculates a checksum on the client side, and S3 validates the checksum server-side.

```js
providerOptions: {
  s3Options: { /* ... */ },
  providerConfig: {
    checksumAlgorithm: 'CRC64NVME', // Options: 'CRC32', 'CRC32C', 'SHA1', 'SHA256', 'CRC64NVME'
  },
},
```

`CRC64NVME` 被推荐用于在现代硬件上获得最佳性能。

### 条件写入（防止覆盖） {#conditional-writes-prevent-overwrites}

🌐 Conditional writes (prevent overwrites)

通过启用条件写入来防止由于竞争条件导致的意外文件覆盖。启用后，如果已经存在具有相同键的对象，上传将会失败。

🌐 Prevent accidental file overwrites due to race conditions by enabling conditional writes. When enabled, uploads will fail if an object with the same key already exists.

```js
providerConfig: {
  preventOverwrite: true,
},
```

### 存储类型（仅限 AWS S3） {#storage-class-aws-s3-only}

🌐 Storage class (AWS S3 only)

通过为上传的对象指定存储类别来优化存储成本。对于不经常访问的数据，请使用成本较低的存储类别。

🌐 Optimize storage costs by specifying a storage class for uploaded objects. Use lower-cost classes for infrequently accessed data.

:::note

存储类是 AWS S3 特有的。其他兼容 S3 的提供商（MinIO、DigitalOcean Spaces、IONOS、Wasabi）将忽略此设置。

🌐 Storage classes are AWS S3-specific. Other S3-compatible providers (MinIO, DigitalOcean Spaces, IONOS, Wasabi) will ignore this setting.

:::

```js
providerConfig: {
  storageClass: 'INTELLIGENT_TIERING', // Auto-optimizes costs
},
```

可用存储类：

🌐 Available storage classes:

- `STANDARD` - 频繁访问的数据（默认）
- `INTELLIGENT_TIERING` - 自动成本优化
- `STANDARD_IA` - 不常访问的数据
- `ONEZONE_IA` - 不常访问，单可用区
- `GLACIER` - 档案存储
- `DEEP_ARCHIVE` - 长期存档
- `GLACIER_IR` - Glacier 即时检索

### 服务器端加密 {#server-side-encryption}

🌐 Server-side encryption

为合规要求（GDPR、HIPAA 等）配置服务器端加密。

🌐 Configure server-side encryption for compliance requirements (GDPR, HIPAA, etc.).

```js
providerConfig: {
  encryption: {
    type: 'AES256', // S3-managed encryption
  },
},
```

对于 KMS 管理的加密（仅适用于 AWS S3）:

🌐 For KMS-managed encryption (AWS S3 only):

```js
providerConfig: {
  encryption: {
    type: 'aws:kms',
    kmsKeyId: env('AWS_KMS_KEY_ID'),
  },
},
```

可用的加密类型：

🌐 Available encryption types:

- `AES256` - S3 管理的密钥（SSE-S3）——大多数兼容 S3 的提供商支持
- `aws:kms` - AWS KMS 管理的密钥（SSE-KMS）——仅限 AWS S3
- `aws:kms:dsse` - 双层 SSE 与 KMS — 仅限 AWS S3

### 对象标记 {#object-tagging}

🌐 Object tagging

对上传的对象应用标签，以进行成本分配、生命周期策略和组织管理。

🌐 Apply tags to uploaded objects for cost allocation, lifecycle policies, and organization.

```js
providerConfig: {
  tags: {
    project: 'website',
    environment: 'production',
    team: 'backend',
  },
},
```

### 多部分上传配置 {#multipart-upload-configuration}

🌐 Multipart upload configuration

配置大文件的分段上传行为。

🌐 Configure multipart upload behavior for large files.

```js
providerConfig: {
  multipart: {
    partSize: 10 * 1024 * 1024, // 10MB per part
    queueSize: 4,               // Number of parallel uploads
    leavePartsOnError: false,   // Clean up on failure
  },
},
```

### 完整配置示例 {#complete-configuration-example}

🌐 Complete configuration example

```js title="/config/plugins.js"
module.exports = ({ env }) => ({
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        baseUrl: env('CDN_URL'),
        rootPath: env('CDN_ROOT_PATH'),
        s3Options: {
          credentials: {
            accessKeyId: env('AWS_ACCESS_KEY_ID'),
            secretAccessKey: env('AWS_ACCESS_SECRET'),
          },
          region: env('AWS_REGION'),
          params: {
            ACL: 'private',
            signedUrlExpires: 15 * 60,
            Bucket: env('AWS_BUCKET'),
          },
        },
        providerConfig: {
          checksumAlgorithm: 'CRC64NVME',
          preventOverwrite: true,
          storageClass: 'INTELLIGENT_TIERING',
          encryption: {
            type: 'aws:kms',
            kmsKeyId: env('AWS_KMS_KEY_ID'),
          },
          tags: {
            application: 'strapi',
            environment: env('NODE_ENV'),
          },
          multipart: {
            partSize: 10 * 1024 * 1024,
            queueSize: 4,
          },
        },
      },
    },
  },
});
```

## 自定义提供程序覆盖（私有 S3 提供程序） {#private-aws-s3-provider}

🌐 Custom provider override (private S3 provider) 

对于大多数私有存储桶的使用场景，在提供程序配置中设置 `ACL: 'private'`（参见 [私有存储桶和签名 URL](#private-bucket-and-signed-urls)）就足够了。提供程序会自动处理 URL 签名。

🌐 For most private bucket use cases, setting `ACL: 'private'` in the provider configuration (see [Private bucket and signed URLs](#private-bucket-and-signed-urls)) is sufficient. The provider handles URL signing automatically.

但是，如果你需要对签名逻辑进行完全控制，你可以在本地重写提供程序。这可以用于为每个文件设置自定义过期时间、条件访问规则，或与外部授权服务的集成。

🌐 However, if you need full control over the signing logic, you can override the provider locally. This could be used to set custom expiration times per file, conditional access rules, or integration with an external authorization service.

要创建自定义 `aws-s3` 提供程序覆盖：

🌐 To create a custom `aws-s3` provider override:

1. 在你的应用中创建一个 `/providers/aws-s3` 文件夹（更多信息请参见 [本地提供者](/cms/configurations/media-library-providers#local-providers)）。
2. 在 `aws-s3` 提供程序中实现 `isPrivate()` 方法以返回 `true`。
3. 在 `aws-s3` 提供者中实现 `getSignedUrl(file)` 方法，以为给定的文件生成签名 URL。

```js title="/providers/aws-s3/index.js"
module.exports = {
  init: (config) => {
    const s3 = new AWS.S3(config);

    return {
      async upload(file) {
        // code to upload file to S3
      },

      async delete(file) {
        // code to delete file from S3
      },

      async isPrivate() {
        return true;
      },

      async getSignedUrl(file) {
        const params = {
          Bucket: config.params.Bucket,
          Key: file.path,
          Expires: 60, // URL expiration time in seconds
        };

        const signedUrl = await s3.getSignedUrlPromise("getObject", params);
        return { url: signedUrl };
      },
    };
  },
};
```

```ts title="/providers/aws-s3/index.ts"

  init: (config) => {
    const s3 = new AWS.S3(config);

    return {
      async upload(file) {
        // code to upload file to S3
      },

      async delete(file) {
        // code to delete file from S3
      },

      async isPrivate() {
        return true;
      },

      async getSignedUrl(file) {
        const params = {
          Bucket: config.params.Bucket,
          Key: file.path,
          Expires: 60, // URL expiration time in seconds
        };

        const signedUrl = await s3.getSignedUrlPromise("getObject", params);
        return { url: signedUrl };
      },
    };
  },
};
```
