在这篇文章中,我们将学习如何在 CKEditor 中集成 Cloudflare R2 对象存储。Cloudflare R2 是一种 S3 兼容的对象存储服务,可以方便地存储和管理静态文件。我们将使用 Go 语言和 Cloudflare 提供的 SDK 来完成文件上传,并通过 CKEditor 进行图像上传。

1. 配置 Cloudflare R2 存储

在开始之前,你需要准备以下信息:

  • Access KeySecret Key: 用于身份验证。
  • R2 存储桶名称: 用于存储文件。
  • 自定义域名公共访问 URL: 用于访问存储中的文件。

示例代码中的配置:

var (
	R2AccessKey  = "your-access-key"
	R2SecretKey  = "your-secret-key"
	R2Endpoint   = "https://your-account-id.r2.cloudflarestorage.com"
	R2Bucket     = "your-bucket-name"
	R2PublicURL  = "https://your-custom-domain-or-public-url"
)

在实际部署时,为了安全起见,你不应该在代码中硬编码敏感的密钥。建议将密钥保存在环境变量中或使用密钥管理系统。

获取key方式: R2 对象存储->{}API->管理 API 令牌

创建 Account API 令牌:获取R2AccessKey  、R2SecretKey   和R2Endpoint

R2PublicURL :启用公共访问url,自定义域名,dns解析下

R2Bucket:创建的存储桶

 

2. 在 Go 中集成 Cloudflare R2

我们将使用 AWS SDK for Go v2 来与 Cloudflare R2 进行交互。由于 R2 是 S3 兼容的,AWS SDK 可以直接与它配合使用。

2.1 配置 R2 客户端

首先,创建一个 getR2Client 函数,用于初始化和配置 Cloudflare R2 客户端:

func getR2Client() (*s3.Client error) {
	customResolver := aws.EndpointResolverWithOptionsFunc(func(service region string options ...interface{}) (aws.Endpoint error) {
		return aws.Endpoint{
			URL:               R2Endpoint
			SigningRegion:     "auto"
			HostnameImmutable: true
		} nil
	})

	cfg err := config.LoadDefaultConfig(context.TODO()
		config.WithRegion("auto")
		config.WithEndpointResolverWithOptions(customResolver)
		config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(R2AccessKey R2SecretKey ""))
	)
	if err != nil {
		return nil err
	}
	return s3.NewFromConfig(cfg) nil
}

2.2 上传文件至 Cloudflare R2

接下来,我们需要定义一个上传文件的函数。这个函数会接收文件内容文件名,并上传到 Cloudflare R2 存储桶:

func UploadToR2(reader io.Reader filename string) (string error) {
	client err := getR2Client()
	if err != nil {
		return "" err
	}

	// key 带时间戳避免冲突
	key := fmt.Sprintf("uploads/%d_%s" time.Now().Unix() filepath.Base(filename))

	uploader := manager.NewUploader(client)
	_ err = uploader.Upload(context.TODO() &s3.PutObjectInput{
		Bucket:       aws.String(R2Bucket)
		Key:          aws.String(key)
		Body:         reader
		ACL:          types.ObjectCannedACLPublicRead
		CacheControl: aws.String("public max-age=31536000") // 缓存一年
	})
	if err != nil {
		return "" err
	}

	// 返回访问 URL
	return fmt.Sprintf("%s/%s" R2PublicURL key) nil
}
  • ACL 设置为 public-read,使上传的文件可以公开访问。
  • CacheControl 设置为 public max-age=31536000,表示文件在浏览器或 CDN 中缓存一年。

3. 配置 CKEditor

3.1 配置 CKEditor 文件上传插件

在 CKEditor 中,我们可以使用 filebrowserUploadUrl 配置项来指定上传文件的接口。你需要将文件上传接口指向我们在 Go 中编写的上传 API。

CKEDITOR.replace('editor1' {
    filebrowserUploadUrl: '/upload' // 上传接口地址
})

3.2 后端上传处理接口

当 CKEditor 上传文件时,它会将文件发送到我们后端的接口。我们可以使用 Go 来处理上传逻辑。

以下是 Go 后端的处理示例:

func uploadHandler(w http.ResponseWriter r *http.Request) {
    file _ err := r.FormFile("upload")
    if err != nil {
        http.Error(w "File upload error" http.StatusBadRequest)
        return
    }
    defer file.Close()

    // 上传文件到 Cloudflare R2
    fileURL err := utils.UploadToR2(file "uploaded_image.jpg")
    if err != nil {
        http.Error(w "Error uploading to R2" http.StatusInternalServerError)
        return
    }

    // 返回文件 URL 给 CKEditor
    jsonResponse := fmt.Sprintf(`{"uploaded": 1 "fileName": "uploaded_image.jpg" "url": "%s"}` fileURL)
    w.Header().Set("Content-Type" "application/json")
    w.Write([]byte(jsonResponse))
}

这个接口会接收 CKEditor 上传的文件,并将其存储在 Cloudflare R2 中。然后,它会返回一个 JSON 响应,包含上传文件的 URL,CKEditor 会将这个 URL 插入到编辑器中。

4. 测试和优化

  • 上传测试: 尝试从 CKEditor 上传图像,检查是否能够正确显示上传后的图片。
  • 缓存验证: 使用浏览器开发者工具,确保图片被缓存,查看 Cache-ControlExpires 头是否设置正确。
  • 安全性: 确保你的 R2 存储桶和密钥的访问控制得当。建议使用环境变量存储密钥,避免暴露在代码中。

5. 总结

通过这篇文章,我们学会了如何将 CKEditorCloudflare R2 集成,实现文件上传并返回访问 URL。我们还配置了适当的 Cache-Control 头,帮助优化文件的缓存管理。确保上传接口的安全性,并使用合适的配置来提高上传和访问速度。

希望这篇文章能帮助你轻松实现 Cloudflare R2 存储的集成。如果有任何问题,欢迎随时联系我!