
后端前端云原生【免费下载链接】hedgedocHedgeDoc - Ideas grow better together项目地址https://gitcode.com/gh_mirrors/he/hedgedoc点击查看免费下载导读HedgeDoc 将笔记中上传的图片Media统一交由可插拔的存储后端处理Imgur 是官方支持的五个后端之一。本文围绕 docs/content/references/config/media/imgur.md 这份配置参考完整讲解如何注册 Imgur 应用、获取 Client ID、通过环境变量启用 Imgur 后端并结合 backend/src/media/backends/imgur-backend.ts 与 backend/src/config/media.config.ts 等源码深入说明上传、删除、URL 解析的实现机制与数据存储结构。读完本文你将能独立完成 HedgeDoc 的 Imgur 后端配置并理解其背后的工作原理与数据留存风险。一、Imgur 在 HedgeDoc 媒体架构中的角色HedgeDoc 的媒体Media指与笔记关联的上传文件目前仅支持图片。媒体文件可以保存在本地文件系统、S3、Azure Blob、通用 WebDAV 共享目录以及 Imgur 上见 docs/content/concepts/media.md。每个存储后端都必须实现统一的 MediaBackend 接口共三个方法saveFile(uuid, buffer, fileType)存储给定文件可返回一段字符串化的元数据交给数据库保存元数据格式由后端自行定义仅供后端内部使用deleteFile(uuid, metadata)根据 UUID 与元数据删除文件getFileUrl(uuid, metadata)返回文件的公开访问 URL该 URL 可以是临时的。Imgur 后端ImgurBackend正是按此接口实现的。启用它之后HedgeDoc 前端上传图片时MediaService会调用该后端将图片二进制数据转发给 Imgur 的匿名上传接口并把 Imgur 返回的链接与删除令牌记录到数据库详见 backend/src/media/media.service.ts。需要特别说明Imgur 作为托管在公网的第三方图床上传的图片会以 Imgur 的域名对外提供访问而非由 HedgeDoc 自身托管。适合希望将图片存储从自有服务器剥离、接受图片托管在第三方平台的部署场景。二、重要提醒匿名图片只有 6 个月存留期!!! warning Imgur 仅保存匿名图片 6 个月 Imgur 会在最后一次访问 6 个月后删除所有未关联到任何账号的图片。 这意味着如果你使用 Imgur 作为图片后端你或你的用户上传的图片可能会丢失。这是官方配置参考文档开篇即给出的警告当 Imgur 应用以“Anonymous usage without user authorization”无需用户授权的匿名使用方式创建时所有上传的图片都不关联任何 Imgur 账号Imgur 将在最后一次被访问的 6 个月后将其删除。官方文档进一步指向了 Imgur 帮助中心的 FAQ 条目作为依据。这一风险意味着长期存档的笔记中的图片可能在 6 个月后 404如果笔记被持续访问图片的“最后一次访问”时间会被刷新存留期会顺延对于需要长期可靠保存图片的部署应优先评估文件系统、S3 等自有后端若只是演示、开发或短期协作场景Imgur 的零运维特性则很有吸引力。配置前请务必与团队确认这一数据留存策略是否可接受。三、注册 Imgur 应用并获取 Client ID启用 Imgur 后端所需的全部准备工作就是注册一个 Imgur 应用并拿到Client ID。官方配置参考给出了如下步骤在 imgur.com 注册一个账号并登录打开 Imgur 的 OAuth2 应用注册页面https://api.imgur.com/oauth2/addclient填写表单并将授权类型Authorization type选择为“Anonymous usage without user authorization”匿名使用无需用户授权提交后Imgur 会显示你的 Client ID。这里强调两点必须选择匿名使用模式。HedgeDoc 的 Imgur 后端在上传时仅携带Client-ID请求头见下文的源码分析并不执行 OAuth 用户授权流程因此应用必须按匿名模式创建Client ID 不同于 Client Secret。配置中只需要 Client ID不要填入任何密钥类信息。四、在 HedgeDoc 中启用 Imgur 后端4.1 配置项一览拿到 Client ID 后在 HedgeDoc 的配置中加入以下两行将IMGUR_CLIENT_ID替换为你的真实 Client IDHD_MEDIA_BACKEND_TYPEimgur HD_MEDIA_BACKEND_IMGUR_CLIENT_IDIMGUR_CLIENT_ID其中环境变量说明取值HD_MEDIA_BACKEND_TYPE选择媒体存储后端类型固定为imgurHD_MEDIA_BACKEND_IMGUR_CLIENT_IDImgur 应用的 Client ID从 Imgur 应用注册页获取的字符串4.2 配置文件的放置位置HedgeDoc 的配置完全由环境变量驱动所有变量以HD_前缀开头。NestJS 会从进程环境以及项目根目录的.env文件中读取这些变量见 docs/content/concepts/config.md。在官方 Docker 容器中.env的位置是/usr/src/app/.env见 docs/content/references/config/index.md。一个同时包含数据库与媒体配置的最小.env示例大致如下HD_BASE_URLhttp://localhost:8080 HD_SESSION_SECRETchange_me_in_production HD_DATABASE_TYPEsqlite HD_DATABASE_NAME./hedgedoc.sqlite HD_MEDIA_BACKEND_TYPEimgur HD_MEDIA_BACKEND_IMGUR_CLIENT_IDyour_client_id_here注意此示例仅为展示媒体配置的书写方式.env.example中提供的是用于本地开发的最小配置不可未经修改直接用于生产。4.3 配置如何被校验媒体配置在 backend/src/config/media.config.ts 中定义。其中 Imgur 相关的 schema 如下const imgurSchema z.object({ type: z.literal(MediaBackendType.IMGUR), imgur: z.object({ clientId: z.string().describe(HD_MEDIA_BACKEND_IMGUR_CLIENT_ID), }), });也就是说type必须严格等于imgurMediaBackendType.IMGUR传入其他值将导致配置校验失败clientId必须是一个字符串缺失时校验会报错并在启动时通过printConfigErrorAndExit打印包含该环境变量名的错误信息后退出进程见 backend/src/config/utils.ts 引用的 utils 与 backend/src/config/zod-error-message.ts。除了后端选择之外该配置文件还定义了上传大小上限HD_MEDIA_MAX_UPLOAD_SIZE默认值为 20 MB20 * 1024 * 1024同样作用于 Imgur 后端。若需调整可一并配置HD_MEDIA_MAX_UPLOAD_SIZE52428800五、源码级原理ImgurBackend 的工作机制5.1 类结构与条件实例化Imgur 后端的实现位于 backend/src/media/backends/imgur-backend.ts。ImgurBackend通过构造函数注入媒体配置并仅在HD_MEDIA_BACKEND_TYPEimgur时才真正读取imgur.clientIdconstructor( private readonly logger: ConsoleLoggerService, Inject(mediaConfiguration.KEY) private mediaConfig: MediaConfig, ) { this.logger.setContext(ImgurBackend.name); // only create the backend if imgur is configured if (this.mediaConfig.backend.type ! MediaBackendType.IMGUR) { return; } this.config this.mediaConfig.backend.imgur; }MediaService在启动时根据配置的backend.type通过getBackendFromType选择对应后端实例Imgur 对应的分支返回moduleRef.get(ImgurBackend)见 backend/src/media/media.service.ts。5.2 上传向 Imgur API 提交 base64 图片saveFile方法把上传文件的二进制内容转为 base64通过 POST 请求发送到 Imgur 的匿名上传接口async saveFile(uuid: string, buffer: Buffer): Promisestring { const params new URLSearchParams(); params.append(image, buffer.toString(base64)); params.append(type, base64); const result (await fetch(https://api.imgur.com/3/image, { method: POST, body: params, headers: { Authorization: Client-ID ${this.config.clientId} }, }) .then((res) ImgurBackend.checkStatus(res)) .then((res) res.json())) as UploadResult; const backendData: ImgurBackendData { url: result.data.link, deleteHash: result.data.deletehash, }; return JSON.stringify(backendData); }关键细节请求头Authorization: Client-ID clientId正是前文“无需用户授权”模式的体现——它只携带应用标识不携带用户令牌Imgur 的响应包含data.link图片公开 URL和data.deletehash删除令牌匿名模式下可据此删除图片可能为null这两个字段被组装成{ url, deleteHash }结构并JSON 序列化后返回作为backendData存入数据库请求失败HTTP 非 2xx会抛出MediaBackendError最终以Could not save file uuid的形式报错。5.3 访问返回重定向 URL由于 Imgur 上的图片本身就是公开 URLgetFileUrl不需要代理字节流只需从数据库中保存的元数据解析出 url 并返回getFileUrl(uuid: string, backendData: string | null): Promisestring { const data JSON.parse(backendData) as ImgurBackendData; return Promise.resolve(data.url); }在 backend/src/media/media.service.ts 的getFileResponse中非文件系统后端统一走redirect分支——即访问媒体接口时HedgeDoc 返回 302 跳转到 Imgur 的图片地址而不是把图片字节流经自己服务器中转。5.4 删除借助 deleteHash 调用匿名删除接口deleteFile会先解析元数据若deleteHash为null比如 Imgur 未返回删除令牌则直接抛出MediaBackendError说明无法删除该图片async deleteFile(uuid: string, jsonBackendData: string): Promisevoid { const backendData JSON.parse(jsonBackendData) as ImgurBackendData; if (backendData.deleteHash null) { throw new MediaBackendError( We dont have any delete tokens for file ${uuid} and therefore cant delete this image, ); } const result await fetch(https://api.imgur.com/3/image/${backendData.deleteHash}, { method: DELETE, headers: { Authorization: Client-ID ${this.config.clientId} }, }); ImgurBackend.checkStatus(result); }可见HedgeDoc 的“删除图片”最终依赖 Imgur 的匿名删除令牌delete hash接口。这也再次印证了文档中“backendData列中保存的是删除令牌”的表述——它是后续删除操作的唯一凭证一旦丢失便无法再从 Imgur 侧删除图片。5.5 上传链路中的 MIME 校验在进入后端之前MediaService.saveFile会先调用 commons/src/file-type/extract-file-type.ts 检测文件类型并与白名单比对不匹配的直接拒绝MIME type not allowed.。白名单覆盖image/png、image/jpeg、image/gif、image/webp、image/svgxml、image/tiff、image/bmp、image/heic等常见图片格式见 backend/src/media/media.service.ts 中的isAllowedMimeType。也就是说只有检测为图片的文件才会被转发给 Imgur。六、上传记录media_uploads 表与 backendData文档明确指出“所有上传都会保存在media_uploads数据库表中并在backendData列中包含删除令牌”。这与源码完全吻合数据库类型定义位于 database/src/types/media-upload.tsTableMediaUpload media_upload关键字段包括uuid媒体上传的公开唯一标识UUID v7user_id上传者file_name原始文件名backend_type存储后端类型Imgur 场景下为imgurbackend_data后端所需的附加元数据——对 Imgur 而言正是{url:...,deleteHash:...}的 JSON 字符串created_at上传时间上传事务见MediaService.saveFile会同时向media_upload表插入记录、向media_upload_note表建立媒体与笔记的关联删除操作MediaService.deleteFile先按uuid查询backend_data交给后端删除成功后再从media_upload表移除记录。因此运维人员可以直接在数据库中查看某张图片的 Imgur 地址与删除令牌便于排查问题或手工清理。七、注意事项小结数据存留匿名模式上传的图片在最后一次访问 6 个月后会被 Imgur 删除长期内容请谨慎选择此后端删除能力图片可删性依赖backendData中的deleteHash缺失时 HedgeDoc 会明确报错并保留记录上传限制默认最大上传 20 MB可通过HD_MEDIA_MAX_UPLOAD_SIZE调整且仅允许白名单内的图片 MIME 类型配置错误定位若HD_MEDIA_BACKEND_TYPE不是imgur或HD_MEDIA_BACKEND_IMGUR_CLIENT_ID缺失HedgeDoc 启动时会打印包含具体环境变量名的错误信息并退出便于快速修正参考实现Imgur 后端的完整行为可在 backend/src/media/backends/imgur-backend.ts 中查看与其他后端S3、Azure、WebDAV、文件系统并列于 backend/src/media/backends/ 目录方便对比各后端的差异。总体而言Imgur 后端是 HedgeDoc 中配置成本最低的图片存储方案之一——只需一个 Client ID、两行环境变量即可启用。但 6 个月的匿名存留期使其更适合短期协作与演示场景对图片有长期留存要求的部署建议在配置前评估文件系统、S3 或 WebDAV 等自有后端方案。赞分享后端前端云原生【免费下载链接】hedgedocHedgeDoc - Ideas grow better together项目地址https://gitcode.com/gh_mirrors/he/hedgedoc点击查看免费下载相关推荐Neon compute 镜像怎么构建扩展补丁、neon 扩展与 vm-image-spec 的作用Neon compute 镜像怎么构建扩展补丁、neon 扩展与 vm image spec 的作用 当你需要给 compute 节点加一个扩展补丁、验证某个后端前端云原生3步搞定Amlogic盒子无线难题RTL8822CS网卡驱动完全指南3步搞定Amlogic盒子无线难题RTL8822CS网卡驱动完全指南 你是否曾为Amlogic S9xxx设备刷入Armbian系统后无线网卡无法使用而烦恼嵌入式开发工具构建工具操作系统使用 rage 作为 chezmoi 的加密后端从配置到源码级原理使用 rage 作为 chezmoi 的加密后端从配置到源码级原理 导读 chezmoi 默认使用 age https://link.gitcode.com/开发工具CLI配置管理上一篇终极EaselJS单元测试指南使用Jasmine框架构建可靠Canvas应用下一篇Sioyek用户反馈改进案例从建议到产品功能的实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考