appwrite-dotnet

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Appwrite .NET SDK

Appwrite .NET SDK

Installation

安装

bash
dotnet add package Appwrite
bash
dotnet add package Appwrite

Setting Up the Client

客户端设置

csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;

var client = new Client()
    .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .SetProject(Environment.GetEnvironmentVariable("APPWRITE_PROJECT_ID"))
    .SetKey(Environment.GetEnvironmentVariable("APPWRITE_API_KEY"));
csharp
using Appwrite;
using Appwrite.Services;
using Appwrite.Models;

var client = new Client()
    .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .SetProject(Environment.GetEnvironmentVariable("APPWRITE_PROJECT_ID"))
    .SetKey(Environment.GetEnvironmentVariable("APPWRITE_API_KEY"));

Code Examples

代码示例

User Management

用户管理

csharp
var users = new Users(client);

// Create user
var user = await users.Create(ID.Unique(), "user@example.com", null, "password123", "User Name");

// List users
var list = await users.List(new List<string> { Query.Limit(25) });

// Get user
var fetched = await users.Get("[USER_ID]");

// Delete user
await users.Delete("[USER_ID]");
csharp
var users = new Users(client);

// 创建用户
var user = await users.Create(ID.Unique(), "user@example.com", null, "password123", "User Name");

// 列出用户
var list = await users.List(new List<string> { Query.Limit(25) });

// 获取用户
var fetched = await users.Get("[USER_ID]");

// 删除用户
await users.Delete("[USER_ID]");

Database Operations

数据库操作

Note: Use
TablesDB
(not the deprecated
Databases
class) for all new code. Only use
Databases
if the existing codebase already relies on it or the user explicitly requests it.
Tip: Prefer named arguments (e.g.,
databaseId: "..."
) for all SDK method calls. Only use positional arguments if the existing codebase already uses them or the user explicitly requests it.
csharp
var tablesDB = new TablesDB(client);

// Create database
var db = await tablesDB.Create(ID.Unique(), "My Database");

// Create row
var doc = await tablesDB.CreateRow("[DATABASE_ID]", "[TABLE_ID]", ID.Unique(),
    new Dictionary<string, object> { { "title", "Hello World" } });

// Query rows
var results = await tablesDB.ListRows("[DATABASE_ID]", "[TABLE_ID]",
    new List<string> { Query.Equal("title", "Hello World"), Query.Limit(10) });

// Get row
var row = await tablesDB.GetRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]");

// Update row
await tablesDB.UpdateRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]",
    new Dictionary<string, object> { { "title", "Updated" } });

// Delete row
await tablesDB.DeleteRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]");
注意: 所有新代码请使用
TablesDB
(而非已弃用的
Databases
类)。仅当现有代码库已依赖
Databases
或用户明确要求时,才使用该类。
提示: 所有SDK方法调用优先使用命名参数(例如
databaseId: "..."
)。仅当现有代码库已使用位置参数或用户明确要求时,才使用位置参数。
csharp
var tablesDB = new TablesDB(client);

// 创建数据库
var db = await tablesDB.Create(ID.Unique(), "My Database");

// 创建行
var doc = await tablesDB.CreateRow("[DATABASE_ID]", "[TABLE_ID]", ID.Unique(),
    new Dictionary<string, object> { { "title", "Hello World" } });

// 查询行
var results = await tablesDB.ListRows("[DATABASE_ID]", "[TABLE_ID]",
    new List<string> { Query.Equal("title", "Hello World"), Query.Limit(10) });

// 获取行
var row = await tablesDB.GetRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]");

// 更新行
await tablesDB.UpdateRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]",
    new Dictionary<string, object> { { "title", "Updated" } });

// 删除行
await tablesDB.DeleteRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]");

String Column Types

字符串列类型

Note: The legacy
string
type is deprecated. Use explicit column types for all new columns.
TypeMax charactersIndexingStorage
varchar
16,383Full index (if size ≤ 768)Inline in row
text
16,383Prefix onlyOff-page
mediumtext
4,194,303Prefix onlyOff-page
longtext
1,073,741,823Prefix onlyOff-page
  • varchar
    is stored inline and counts towards the 64 KB row size limit. Prefer for short, indexed fields like names, slugs, or identifiers.
  • text
    ,
    mediumtext
    , and
    longtext
    are stored off-page (only a 20-byte pointer lives in the row), so they don't consume the row size budget.
    size
    is not required for these types.
csharp
// Create table with explicit string column types
await tablesDB.CreateTable("[DATABASE_ID]", ID.Unique(), "articles",
    new List<object> {
        new { key = "title",    type = "varchar",    size = 255, required = true  },  // inline, fully indexable
        new { key = "summary",  type = "text",                   required = false },  // off-page, prefix index only
        new { key = "body",     type = "mediumtext",             required = false },  // up to ~4 M chars
        new { key = "raw_data", type = "longtext",               required = false },  // up to ~1 B chars
    });
注意: 旧版
string
类型已弃用。所有新列请使用明确的列类型。
类型最大字符数索引方式存储位置
varchar
16,383全索引(若长度≤768)行内存储
text
16,383仅前缀索引页外存储
mediumtext
4,194,303仅前缀索引页外存储
longtext
1,073,741,823仅前缀索引页外存储
  • varchar
    存储在行内,占用64 KB行大小限制。适合短的、需要索引的字段,如名称、别名或标识符。
  • text
    mediumtext
    longtext
    存储在页外(行中仅保留20字节的指针),因此不会占用行大小配额。这些类型不需要指定
    size
csharp
// 创建包含明确字符串列类型的表
await tablesDB.CreateTable("[DATABASE_ID]", ID.Unique(), "articles",
    new List<object> {
        new { key = "title",    type = "varchar",    size = 255, required = true  },  // 行内存储,可全索引
        new { key = "summary",  type = "text",                   required = false },  // 页外存储,仅前缀索引
        new { key = "body",     type = "mediumtext",             required = false },  // 最多约400万字符
        new { key = "raw_data", type = "longtext",               required = false },  // 最多约10亿字符
    });

Query Methods

查询方法

csharp
// Filtering
Query.Equal("field", "value")             // == (or pass array for IN)
Query.NotEqual("field", "value")          // !=
Query.LessThan("field", 100)             // <
Query.LessThanEqual("field", 100)        // <=
Query.GreaterThan("field", 100)          // >
Query.GreaterThanEqual("field", 100)     // >=
Query.Between("field", 1, 100)           // 1 <= field <= 100
Query.IsNull("field")                    // is null
Query.IsNotNull("field")                 // is not null
Query.StartsWith("field", "prefix")      // starts with
Query.EndsWith("field", "suffix")        // ends with
Query.Contains("field", "sub")           // contains
Query.Search("field", "keywords")        // full-text search (requires index)

// Sorting
Query.OrderAsc("field")
Query.OrderDesc("field")

// Pagination
Query.Limit(25)                          // max rows (default 25, max 100)
Query.Offset(0)                          // skip N rows
Query.CursorAfter("[ROW_ID]")            // cursor pagination (preferred)
Query.CursorBefore("[ROW_ID]")

// Selection & Logic
Query.Select(new List<string> { "field1", "field2" })
Query.Or(new List<string> { Query.Equal("a", 1), Query.Equal("b", 2) })   // OR
Query.And(new List<string> { Query.GreaterThan("age", 18), Query.LessThan("age", 65) })  // AND (default)
csharp
// 过滤
Query.Equal("field", "value")             // ==(传入数组则为IN查询)
Query.NotEqual("field", "value")          // !=
Query.LessThan("field", 100)             // <
Query.LessThanEqual("field", 100)        // <=
Query.GreaterThan("field", 100)          // >
Query.GreaterThanEqual("field", 100)     // >=
Query.Between("field", 1, 100)           // 1 <= 字段 <= 100
Query.IsNull("field")                    // 为空
Query.IsNotNull("field")                 // 不为空
Query.StartsWith("field", "prefix")      // 以指定前缀开头
Query.EndsWith("field", "suffix")        // 以指定后缀结尾
Query.Contains("field", "sub")           // 包含指定子串
Query.Search("field", "keywords")        // 全文搜索(需要索引)

// 排序
Query.OrderAsc("field")
Query.OrderDesc("field")

// 分页
Query.Limit(25)                          // 最大行数(默认25,最大100)
Query.Offset(0)                          // 跳过N行
Query.CursorAfter("[ROW_ID]")            // 游标分页(推荐使用)
Query.CursorBefore("[ROW_ID]")

// 字段选择与逻辑
Query.Select(new List<string> { "field1", "field2" })
Query.Or(new List<string> { Query.Equal("a", 1), Query.Equal("b", 2) })   // 或
Query.And(new List<string> { Query.GreaterThan("age", 18), Query.LessThan("age", 65) })  // 与(默认逻辑)

File Storage

文件存储

csharp
var storage = new Storage(client);

// Upload file
var file = await storage.CreateFile("[BUCKET_ID]", ID.Unique(), InputFile.FromPath("/path/to/file.png"));

// List files
var files = await storage.ListFiles("[BUCKET_ID]");

// Delete file
await storage.DeleteFile("[BUCKET_ID]", "[FILE_ID]");
csharp
var storage = new Storage(client);

// 上传文件
var file = await storage.CreateFile("[BUCKET_ID]", ID.Unique(), InputFile.FromPath("/path/to/file.png"));

// 列出文件
var files = await storage.ListFiles("[BUCKET_ID]");

// 删除文件
await storage.DeleteFile("[BUCKET_ID]", "[FILE_ID]");

InputFile Factory Methods

InputFile 工厂方法

csharp
using Appwrite.Models;

InputFile.FromPath("/path/to/file.png")                          // from filesystem path
InputFile.FromBytes(byteArray, "file.png", "image/png")          // from byte[]
InputFile.FromStream(stream, "file.png", "image/png", size)      // from Stream (size required)
csharp
using Appwrite.Models;

InputFile.FromPath("/path/to/file.png")                          // 从文件系统路径创建
InputFile.FromBytes(byteArray, "file.png", "image/png")          // 从byte[]创建
InputFile.FromStream(stream, "file.png", "image/png", size)      // 从Stream创建(需要指定size)

Teams

团队管理

csharp
var teams = new Teams(client);

// Create team
var team = await teams.Create(ID.Unique(), "Engineering");

// List teams
var list = await teams.List();

// Create membership (invite user by email)
var membership = await teams.CreateMembership(
    teamId: "[TEAM_ID]",
    roles: new List<string> { "editor" },
    email: "user@example.com"
);

// List memberships
var members = await teams.ListMemberships("[TEAM_ID]");

// Update membership roles
await teams.UpdateMembership("[TEAM_ID]", "[MEMBERSHIP_ID]", new List<string> { "admin" });

// Delete team
await teams.Delete("[TEAM_ID]");
Role-based access: Use
Role.Team("[TEAM_ID]")
for all team members or
Role.Team("[TEAM_ID]", "editor")
for a specific team role when setting permissions.
csharp
var teams = new Teams(client);

// 创建团队
var team = await teams.Create(ID.Unique(), "Engineering");

// 列出团队
var list = await teams.List();

// 创建成员身份(通过邮箱邀请用户)
var membership = await teams.CreateMembership(
    teamId: "[TEAM_ID]",
    roles: new List<string> { "editor" },
    email: "user@example.com"
);

// 列出成员身份
var members = await teams.ListMemberships("[TEAM_ID]");

// 更新成员角色
await teams.UpdateMembership("[TEAM_ID]", "[MEMBERSHIP_ID]", new List<string> { "admin" });

// 删除团队
await teams.Delete("[TEAM_ID]");
基于角色的访问控制: 设置权限时,使用
Role.Team("[TEAM_ID]")
表示所有团队成员,或使用
Role.Team("[TEAM_ID]", "editor")
表示特定团队角色。

Serverless Functions

无服务器函数

csharp
var functions = new Functions(client);

// Execute function
var execution = await functions.CreateExecution("[FUNCTION_ID]", body: "{\"key\": \"value\"}");

// List executions
var executions = await functions.ListExecutions("[FUNCTION_ID]");
csharp
var functions = new Functions(client);

// 执行函数
var execution = await functions.CreateExecution("[FUNCTION_ID]", body: "{\"key\": \"value\"}");

// 列出执行记录
var executions = await functions.ListExecutions("[FUNCTION_ID]");

Writing a Function Handler (.NET runtime)

编写函数处理程序(.NET运行时)

csharp
// src/Main.cs — Appwrite Function entry point
using System.Text.Json;

public async Task<RuntimeOutput> Main(RuntimeContext context)
{
    // context.Req.Body        — raw body (string)
    // context.Req.BodyJson    — parsed JSON (JsonElement)
    // context.Req.Headers     — headers (Dictionary)
    // context.Req.Method      — HTTP method
    // context.Req.Path        — URL path
    // context.Req.Query       — query params (Dictionary)

    context.Log($"Processing: {context.Req.Method} {context.Req.Path}");

    if (context.Req.Method == "GET")
        return context.Res.Json(new { message = "Hello from Appwrite Function!" });

    return context.Res.Json(new { success = true });      // JSON
    // context.Res.Text("Hello");                         // plain text
    // context.Res.Empty();                               // 204
    // context.Res.Redirect("https://...");               // 302
}
csharp
// src/Main.cs — Appwrite 函数入口点
using System.Text.Json;

public async Task<RuntimeOutput> Main(RuntimeContext context)
{
    // context.Req.Body        — 原始请求体(字符串)
    // context.Req.BodyJson    — 解析后的JSON(JsonElement)
    // context.Req.Headers     — 请求头(字典)
    // context.Req.Method      — HTTP方法
    // context.Req.Path        — URL路径
    // context.Req.Query       — 查询参数(字典)

    context.Log($"Processing: {context.Req.Method} {context.Req.Path}");

    if (context.Req.Method == "GET")
        return context.Res.Json(new { message = "Hello from Appwrite Function!" });

    return context.Res.Json(new { success = true });      // 返回JSON
    // context.Res.Text("Hello");                         // 返回纯文本
    // context.Res.Empty();                               // 返回204无内容
    // context.Res.Redirect("https://...");               // 返回302重定向
}

Server-Side Rendering (SSR) Authentication

服务器端渲染(SSR)身份验证

SSR apps using .NET frameworks (ASP.NET, Blazor Server, etc.) use the server SDK to handle auth. You need two clients:
  • Admin client — uses an API key, creates sessions, bypasses rate limits (reusable singleton)
  • Session client — uses a session cookie, acts on behalf of a user (create per-request, never share)
csharp
using Appwrite;
using Appwrite.Services;

// Admin client (reusable)
var adminClient = new Client()
    .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .SetProject("[PROJECT_ID]")
    .SetKey(Environment.GetEnvironmentVariable("APPWRITE_API_KEY"));

// Session client (create per-request)
var sessionClient = new Client()
    .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .SetProject("[PROJECT_ID]");

var session = Request.Cookies["a_session_[PROJECT_ID]"];
if (session != null)
{
    sessionClient.SetSession(session);
}
使用.NET框架(ASP.NET、Blazor Server等)的SSR应用通过服务器SDK处理身份验证。你需要两个客户端:
  • 管理员客户端 — 使用API密钥,可创建会话,绕过速率限制(可复用单例)
  • 会话客户端 — 使用会话Cookie,代表用户执行操作(每个请求创建一个,切勿共享)
csharp
using Appwrite;
using Appwrite.Services;

// 管理员客户端(可复用)
var adminClient = new Client()
    .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .SetProject("[PROJECT_ID]")
    .SetKey(Environment.GetEnvironmentVariable("APPWRITE_API_KEY"));

// 会话客户端(每个请求创建)
var sessionClient = new Client()
    .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")
    .SetProject("[PROJECT_ID]");

var session = Request.Cookies["a_session_[PROJECT_ID]"];
if (session != null)
{
    sessionClient.SetSession(session);
}

Email/Password Login (ASP.NET Minimal API)

邮箱/密码登录(ASP.NET Minimal API)

csharp
app.MapPost("/login", async (HttpContext ctx, LoginRequest body) =>
{
    var account = new Account(adminClient);
    var session = await account.CreateEmailPasswordSession(body.Email, body.Password);

    // Cookie name must be a_session_<PROJECT_ID>
    ctx.Response.Cookies.Append("a_session_[PROJECT_ID]", session.Secret, new CookieOptions
    {
        HttpOnly = true,
        Secure = true,
        SameSite = SameSiteMode.Strict,
        Path = "/",
    });

    return Results.Ok(new { success = true });
});
csharp
app.MapPost("/login", async (HttpContext ctx, LoginRequest body) =>
{
    var account = new Account(adminClient);
    var session = await account.CreateEmailPasswordSession(body.Email, body.Password);

    // Cookie名称必须为a_session_<PROJECT_ID>
    ctx.Response.Cookies.Append("a_session_[PROJECT_ID]", session.Secret, new CookieOptions
    {
        HttpOnly = true,
        Secure = true,
        SameSite = SameSiteMode.Strict,
        Path = "/",
    });

    return Results.Ok(new { success = true });
});

Authenticated Requests

已验证请求

csharp
app.MapGet("/user", async (HttpContext ctx) =>
{
    var session = ctx.Request.Cookies["a_session_[PROJECT_ID]"];
    if (session == null) return Results.Unauthorized();

    var sessionClient = new Client()
        .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")
        .SetProject("[PROJECT_ID]")
        .SetSession(session);

    var account = new Account(sessionClient);
    var user = await account.Get();
    return Results.Ok(user);
});
csharp
app.MapGet("/user", async (HttpContext ctx) =>
{
    var session = ctx.Request.Cookies["a_session_[PROJECT_ID]"];
    if (session == null) return Results.Unauthorized();

    var sessionClient = new Client()
        .SetEndpoint("https://<REGION>.cloud.appwrite.io/v1")
        .SetProject("[PROJECT_ID]")
        .SetSession(session);

    var account = new Account(sessionClient);
    var user = await account.Get();
    return Results.Ok(user);
});

OAuth2 SSR Flow

OAuth2 SSR 流程

csharp
// Step 1: Redirect to OAuth provider
app.MapGet("/oauth", async () =>
{
    var account = new Account(adminClient);
    var redirectUrl = await account.CreateOAuth2Token(
        provider: OAuthProvider.Github,
        success: "https://example.com/oauth/success",
        failure: "https://example.com/oauth/failure"
    );
    return Results.Redirect(redirectUrl);
});

// Step 2: Handle callback — exchange token for session
app.MapGet("/oauth/success", async (HttpContext ctx, string userId, string secret) =>
{
    var account = new Account(adminClient);
    var session = await account.CreateSession(userId, secret);

    ctx.Response.Cookies.Append("a_session_[PROJECT_ID]", session.Secret, new CookieOptions
    {
        HttpOnly = true, Secure = true, SameSite = SameSiteMode.Strict, Path = "/",
    });

    return Results.Ok(new { success = true });
});
Cookie security: Always use
HttpOnly
,
Secure
, and
SameSite = SameSiteMode.Strict
to prevent XSS. The cookie name must be
a_session_<PROJECT_ID>
.
Forwarding user agent: Call
sessionClient.SetForwardedUserAgent(ctx.Request.Headers["User-Agent"])
to record the end-user's browser info for debugging and security.
csharp
// 步骤1:重定向到OAuth提供商
app.MapGet("/oauth", async () =>
{
    var account = new Account(adminClient);
    var redirectUrl = await account.CreateOAuth2Token(
        provider: OAuthProvider.Github,
        success: "https://example.com/oauth/success",
        failure: "https://example.com/oauth/failure"
    );
    return Results.Redirect(redirectUrl);
});

// 步骤2:处理回调 — 交换令牌获取会话
app.MapGet("/oauth/success", async (HttpContext ctx, string userId, string secret) =>
{
    var account = new Account(adminClient);
    var session = await account.CreateSession(userId, secret);

    ctx.Response.Cookies.Append("a_session_[PROJECT_ID]", session.Secret, new CookieOptions
    {
        HttpOnly = true, Secure = true, SameSite = SameSiteMode.Strict, Path = "/",
    });

    return Results.Ok(new { success = true });
});
Cookie安全性: 始终使用
HttpOnly
Secure
SameSite = SameSiteMode.Strict
以防止XSS攻击。Cookie名称必须为
a_session_<PROJECT_ID>
转发用户代理: 调用
sessionClient.SetForwardedUserAgent(ctx.Request.Headers["User-Agent"])
以记录终端用户的浏览器信息,用于调试和安全目的。

Error Handling

错误处理

csharp
using Appwrite;

try
{
    var row = await tablesDB.GetRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]");
}
catch (AppwriteException e)
{
    Console.WriteLine(e.Message);    // human-readable message
    Console.WriteLine(e.Code);       // HTTP status code (int)
    Console.WriteLine(e.Type);       // error type (e.g. "document_not_found")
    Console.WriteLine(e.Response);   // full response body
}
Common error codes:
CodeMeaning
401
Unauthorized — missing or invalid session/API key
403
Forbidden — insufficient permissions
404
Not found — resource does not exist
409
Conflict — duplicate ID or unique constraint
429
Rate limited — too many requests
csharp
using Appwrite;

try
{
    var row = await tablesDB.GetRow("[DATABASE_ID]", "[TABLE_ID]", "[ROW_ID]");
}
catch (AppwriteException e)
{
    Console.WriteLine(e.Message);    // 人类可读消息
    Console.WriteLine(e.Code);       // HTTP状态码(整数)
    Console.WriteLine(e.Type);       // 错误类型(例如"document_not_found")
    Console.WriteLine(e.Response);   // 完整响应体
}
常见错误码:
代码含义
401
未授权 — 缺少或无效的会话/API密钥
403
禁止访问 — 权限不足
404
未找到 — 资源不存在
409
冲突 — 重复ID或唯一约束冲突
429
请求受限 — 请求过于频繁

Permissions & Roles (Critical)

权限与角色(关键)

Appwrite uses permission strings to control access to resources. Each permission pairs an action (
read
,
update
,
delete
,
create
, or
write
which grants create + update + delete) with a role target. By default, no user has access unless permissions are explicitly set at the document/file level or inherited from the collection/bucket settings. Permissions are arrays of strings built with the
Permission
and
Role
helpers.
csharp
using Appwrite;
// Permission and Role are included in the main namespace
Appwrite使用权限字符串控制资源访问。每个权限将操作(
read
update
delete
create
write
,后者包含create+update+delete)与角色目标配对。默认情况下,所有用户都无访问权限,除非在文档/文件级别显式设置权限,或从集合/存储桶设置继承权限。权限是通过
Permission
Role
助手构建的字符串数组。
csharp
using Appwrite;
// Permission和Role已包含在主命名空间中

Database Row with Permissions

带权限的数据库行

csharp
var doc = await tablesDB.CreateRow("[DATABASE_ID]", "[TABLE_ID]", ID.Unique(),
    new Dictionary<string, object> { { "title", "Hello World" } },
    new List<string>
    {
        Permission.Read(Role.User("[USER_ID]")),     // specific user can read
        Permission.Update(Role.User("[USER_ID]")),   // specific user can update
        Permission.Read(Role.Team("[TEAM_ID]")),     // all team members can read
        Permission.Read(Role.Any()),                 // anyone (including guests) can read
    });
csharp
var doc = await tablesDB.CreateRow("[DATABASE_ID]", "[TABLE_ID]", ID.Unique(),
    new Dictionary<string, object> { { "title", "Hello World" } },
    new List<string>
    {
        Permission.Read(Role.User("[USER_ID]")),     // 指定用户可读取
        Permission.Update(Role.User("[USER_ID]")),   // 指定用户可更新
        Permission.Read(Role.Team("[TEAM_ID]")),     // 所有团队成员可读取
        Permission.Read(Role.Any()),                 // 任何人(包括访客)可读取
    });

File Upload with Permissions

带权限的文件上传

csharp
var file = await storage.CreateFile("[BUCKET_ID]", ID.Unique(),
    InputFile.FromPath("/path/to/file.png"),
    new List<string>
    {
        Permission.Read(Role.Any()),
        Permission.Update(Role.User("[USER_ID]")),
        Permission.Delete(Role.User("[USER_ID]")),
    });
When to set permissions: Set document/file-level permissions when you need per-resource access control. If all documents in a collection share the same rules, configure permissions at the collection/bucket level and leave document permissions empty.
Common mistakes:
  • Forgetting permissions — the resource becomes inaccessible to all users (including the creator)
  • Role.Any()
    with
    write
    /
    update
    /
    delete
    — allows any user, including unauthenticated guests, to modify or remove the resource
  • Permission.Read(Role.Any())
    on sensitive data
    — makes the resource publicly readable
csharp
var file = await storage.CreateFile("[BUCKET_ID]", ID.Unique(),
    InputFile.FromPath("/path/to/file.png"),
    new List<string>
    {
        Permission.Read(Role.Any()),
        Permission.Update(Role.User("[USER_ID]")),
        Permission.Delete(Role.User("[USER_ID]")),
    });
何时设置权限: 当需要按资源设置访问控制时,在文档/文件级别设置权限。如果集合中的所有文档共享相同规则,请在集合/存储桶级别配置权限,文档级权限留空即可。
常见错误:
  • 忘记设置权限 — 资源对所有用户(包括创建者)都不可访问
  • write
    /
    update
    /
    delete
    使用
    Role.Any()
    — 允许任何用户(包括未认证访客)修改或删除资源
  • 对敏感数据使用
    Permission.Read(Role.Any())
    — 使资源可公开读取