feat: convert attachment path to ArrayBuffer

This commit is contained in:
eoao
2026-05-10 18:33:54 +08:00
parent f6eaf6d0fd
commit fdf4259701
5 changed files with 64 additions and 27 deletions

View File

@@ -91,13 +91,10 @@ const attService = {
if (src.startsWith(domainUtils.toOssDomain(r2Domain))) { if (src.startsWith(domainUtils.toOssDomain(r2Domain))) {
attData.key = src.replace(domainUtils.toOssDomain(r2Domain) + '/',''); attData.key = src.replace(domainUtils.toOssDomain(r2Domain) + '/','');
attData.path = src;
} }
if (src.startsWith('attachments/')) { if (src.startsWith('attachments/')) {
const origin = new URL(c.req.url).origin;
attData.key = src; attData.key = src;
attData.path = origin + '/' + src;
} }
attData.contentId = cid; attData.contentId = cid;
@@ -117,22 +114,34 @@ const attService = {
} }
//查询已有内嵌url图片信息 //查询已有内嵌url图片信息
const keys = [...new Set(imageDataList.filter(item => item.path).map(item => item.key))]; const keys = [...new Set(imageDataList.filter(item => !item.content).map(item => item.key))];
const dbImageList = await this.selectOneByKeys(c, keys); const dbImageList = await this.selectOneByKeys(c, keys);
//设置给当前附件 //设置给当前附件
imageDataList.forEach(image => { await Promise.all(imageDataList.map(async image => {
dbImageList.forEach(dbImage => { if (image.content) {
if (image.path && (image.key === dbImage.key)) { return;
image.size = dbImage.size; }
image.filename = dbImage.filename;
image.mimeType = dbImage.mimeType;
image.contentType = dbImage.mimeType;
}
})
})
imageDataList = imageDataList.filter(image => !image.path || image.size); const dbImage = dbImageList.find(dbImage => image.key === dbImage.key);
if (!dbImage) {
return;
}
image.size = dbImage.size;
image.filename = dbImage.filename;
image.mimeType = dbImage.mimeType;
image.contentType = dbImage.mimeType;
const obj = await r2Service.getObj(c, image.key);
if (!obj) {
return;
}
image.content = obj instanceof ArrayBuffer ? obj : await obj.arrayBuffer();
}))
imageDataList = imageDataList.filter(image => image.content);
return { imageDataList, html: document.toString() }; return { imageDataList, html: document.toString() };
}, },

View File

@@ -472,14 +472,6 @@ const emailService = {
async toAttachmentArrayBuffer(attachment) { async toAttachmentArrayBuffer(attachment) {
let content = attachment.content; let content = attachment.content;
if (!content && attachment.path) {
const response = await fetch(attachment.path);
if (!response.ok) {
throw new BizError(`Attachment fetch failed: ${attachment.filename}`);
}
return await response.arrayBuffer();
}
if (!content) { if (!content) {
return null; return null;
} }

View File

@@ -17,9 +17,11 @@ const kvObjService = {
await Promise.all(keys.map( key => c.env.kv.delete(key))); await Promise.all(keys.map( key => c.env.kv.delete(key)));
}, },
async toObjResp(c, key) { async getObj(c, key) {
const obj = await c.env.kv.getWithMetadata(key, { type: "arrayBuffer"}); const obj = await c.env.kv.getWithMetadata(key, { type: "arrayBuffer"});
if (!obj.value) {
return null;
}
return new Response(obj.value, { return new Response(obj.value, {
headers: { headers: {
@@ -28,6 +30,11 @@ const kvObjService = {
'Cache-Control': obj.metadata?.cacheControl || null 'Cache-Control': obj.metadata?.cacheControl || null
} }
}); });
},
async toObjResp(c, key) {
return await this.getObj(c, key);
} }

View File

@@ -41,7 +41,19 @@ const r2Service = {
}, },
async getObj(c, key) { async getObj(c, key) {
return await c.env.r2.get(key); const storageType = await this.storageType(c);
if (storageType === 'KV') {
return await kvObjService.getObj(c, key);
}
if (storageType === 'R2') {
return await c.env.r2.get(key);
}
if (storageType === 'S3') {
return await s3Service.getObj(c, key);
}
}, },
async delete(c, key) { async delete(c, key) {

View File

@@ -1,4 +1,4 @@
import { S3Client, PutObjectCommand, DeleteObjectsCommand } from "@aws-sdk/client-s3"; import { S3Client, PutObjectCommand, DeleteObjectsCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import settingService from './setting-service'; import settingService from './setting-service';
import domainUtils from '../utils/domain-uitls'; import domainUtils from '../utils/domain-uitls';
import { settingConst } from '../const/entity-const'; import { settingConst } from '../const/entity-const';
@@ -75,6 +75,23 @@ const s3Service = {
); );
}, },
async getObj(c, key) {
const client = await this.client(c);
const { bucket } = await settingService.query(c);
const result = await client.send(new GetObjectCommand({
Bucket: bucket,
Key: key
}));
return new Response(result.Body, {
headers: {
'Content-Type': result.ContentType || 'application/octet-stream',
'Content-Disposition': result.ContentDisposition || null,
'Cache-Control': result.CacheControl || null
}
});
},
async client(c) { async client(c) {
const { region, endpoint, s3AccessKey, s3SecretKey, forcePathStyle } = await settingService.query(c); const { region, endpoint, s3AccessKey, s3SecretKey, forcePathStyle } = await settingService.query(c);