diff --git a/src/core/apis/file.ts b/src/core/apis/file.ts
index 27f5ebaf..c4705071 100644
--- a/src/core/apis/file.ts
+++ b/src/core/apis/file.ts
@@ -365,22 +365,41 @@ export class NTQQFileApi {
 
         if (url) {
             const parsedUrl = new URL(IMAGE_HTTP_HOST + url);
+            const urlRkey = parsedUrl.searchParams.get('rkey');
             const imageAppid = parsedUrl.searchParams.get('appid');
             const isNTV2 = imageAppid && ['1406', '1407'].includes(imageAppid);
-            if (isNTV2) {
-                let rkey = parsedUrl.searchParams.get('rkey');
-                if (rkey) {
-                    return IMAGE_HTTP_HOST_NT + url;
-                }
-                const rkeyData = await this.rkeyManager.getRkey();
-                rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
-                return IMAGE_HTTP_HOST_NT + url + `${rkey}`;
-            } else {
-                return IMAGE_HTTP_HOST + url;
+            const imageFileId = parsedUrl.searchParams.get('fileid');
+
+            let rkeyData = {
+                private_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qEc3Rbib9LP4',
+                group_rkey: 'CAQSKAB6JWENi5LM_xp9vumLbuThJSaYf-yzMrbZsuq7Uz2qffcqm614gds',
+                online_rkey: false
+            };
+
+            try {
+                let tempRkeyData = await this.rkeyManager.getRkey();
+                rkeyData.group_rkey = tempRkeyData.group_rkey;
+                rkeyData.private_rkey = tempRkeyData.private_rkey;
+                rkeyData.online_rkey = tempRkeyData.expired_time > Date.now() / 1000;
+            } catch (e) {
+                this.context.logger.logError.bind(this.context.logger)('获取rkey失败 Fallback Old Mode', e);
             }
+
+
+            if (isNTV2 && urlRkey) {
+                return IMAGE_HTTP_HOST_NT + urlRkey;
+            } else if (isNTV2 && rkeyData.online_rkey) {
+                let rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
+                return IMAGE_HTTP_HOST_NT + url + `&rkey=${rkey}`;
+            } else if (isNTV2 && imageFileId) {
+                let rkey = imageAppid === '1406' ? rkeyData.private_rkey : rkeyData.group_rkey;
+                return IMAGE_HTTP_HOST + `/download?appid=${imageAppid}&fileid=${imageFileId}&rkey=${rkey}`;
+            }
+
         } else if (fileMd5 || md5HexStr) {
             return `${IMAGE_HTTP_HOST}/gchatpic_new/0/0-0-${(fileMd5 ?? md5HexStr)!.toUpperCase()}/0`;
         }
+
         this.context.logger.logDebug('图片url获取失败', element);
         return '';
     }
diff --git a/src/core/helper/rkey.ts b/src/core/helper/rkey.ts
index 0c74f45c..852cafed 100644
--- a/src/core/helper/rkey.ts
+++ b/src/core/helper/rkey.ts
@@ -26,7 +26,8 @@ export class RkeyManager {
             try {
                 await this.refreshRkey();
             } catch (e) {
-                this.logger.logError.bind(this.logger)('获取rkey失败', e);
+                throw new Error(`获取rkey失败: ${e}`);//外抛
+                //this.logger.logError.bind(this.logger)('获取rkey失败', e);
             }
         }
         return this.rkeyData;
@@ -42,9 +43,18 @@ export class RkeyManager {
         //刷新rkey
         for (const url of this.serverUrl) {
             try {
-                this.rkeyData = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET');
+                let temp = await RequestUtil.HttpGetJson<ServerRkeyData>(url, 'GET');
+                this.rkeyData = {
+                    group_rkey: temp.group_rkey.slice(6),
+                    private_rkey: temp.private_rkey.slice(6),
+                    expired_time: temp.expired_time
+                };
             } catch (e) {
                 this.logger.logError.bind(this.logger)(`[Rkey] Get Rkey ${url} Error `, e);
+                //是否为最后一个url
+                if (url === this.serverUrl[this.serverUrl.length - 1]) {
+                    throw new Error(`获取rkey失败: ${e}`);//外抛
+                }
             }
         }
 
diff --git a/src/core/proto/ImageFileId.ts b/src/core/proto/ImageFileId.ts
new file mode 100644
index 00000000..25ad0ee7
--- /dev/null
+++ b/src/core/proto/ImageFileId.ts
@@ -0,0 +1,21 @@
+import { MessageType, BinaryReader, ScalarType, BinaryWriter } from '@protobuf-ts/runtime';
+
+export const FileId = new MessageType("FileId", [
+    { no: 2, name: "sha1", kind: "scalar", T: ScalarType.BYTES },
+    { no: 4, name: "appid", kind: "scalar", T: ScalarType.UINT32 },
+]);
+
+export function encodePBFileId(message: any) {
+    return FileId.internalBinaryWrite(message, new BinaryWriter(), {
+        writerFactory: () => new BinaryWriter(),
+        writeUnknownFields: false
+    }).finish();
+}
+
+export function decodePBFileId(buffer: Uint8Array): any {
+    const reader = new BinaryReader(buffer);
+    return FileId.internalBinaryRead(reader, reader.len, {
+        readUnknownField: true,
+        readerFactory: () => new BinaryReader(buffer)
+    });
+}
\ No newline at end of file