fix: upload Douban images to PicGo via temp file

This commit is contained in:
ChrsiGray 2026-03-27 18:18:43 +08:00
parent a8094d7575
commit 217c56cd73
3 changed files with 89 additions and 16 deletions

@ -543,15 +543,24 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
} }
fileName = this.parsePartPath(fileName, extract, context, variableMap) fileName = this.parsePartPath(fileName, extract, context, variableMap)
fileName = fileName + fileNameSuffix; fileName = fileName + fileNameSuffix;
// const referHeaders = {'referer': image}; const imageReferer = extract.url || extract.imageUrl || image;
const referHeaders = context.settings.loginHeadersContent ? JSON.parse(context.settings.loginHeadersContent) : {}; const referHeaders = HttpUtil.buildImageRequestHeaders(
context.plugin.settingsManager.getHeaders() as Record<string, any>,
imageReferer,
image
);
if ((syncConfig ? syncConfig.cacheHighQuantityImage : context.settings.cacheHighQuantityImage) && context.userComponent.isLogin()) { if ((syncConfig ? syncConfig.cacheHighQuantityImage : context.settings.cacheHighQuantityImage) && context.userComponent.isLogin()) {
try { try {
const fileNameSpilt = fileName.split('.'); const fileNameSpilt = fileName.split('.');
const highFilename = fileNameSpilt.first() + '.jpg'; const highFilename = fileNameSpilt.first() + '.jpg';
const highImage = this.getHighQuantityImageUrl(highFilename); const highImage = this.getHighQuantityImageUrl(highFilename);
const resultValue = await this.handleImage(highImage, folder, highFilename, context, false, referHeaders); const highImageHeaders = HttpUtil.buildImageRequestHeaders(
context.plugin.settingsManager.getHeaders() as Record<string, any>,
imageReferer,
highImage
);
const resultValue = await this.handleImage(highImage, folder, highFilename, context, false, highImageHeaders);
if (resultValue && resultValue.success) { if (resultValue && resultValue.success) {
extract.image = resultValue.filepath; extract.image = resultValue.filepath;
this.initImageVariableMap(extract, context, variableMap); this.initImageVariableMap(extract, context, variableMap);

@ -5,7 +5,6 @@ import FileHandler from "../file/FileHandler";
import {FileUtil} from "../utils/FileUtil"; import {FileUtil} from "../utils/FileUtil";
import HandleContext from "../douban/data/model/HandleContext"; import HandleContext from "../douban/data/model/HandleContext";
import HttpUtil from "../utils/HttpUtil"; import HttpUtil from "../utils/HttpUtil";
import {ClipboardUtil} from "../utils/ClipboardUtil";
import {ResultI} from "../utils/model/Result"; import {ResultI} from "../utils/model/Result";
export default class NetFileHandler { export default class NetFileHandler {
@ -61,10 +60,14 @@ export default class NetFileHandler {
} }
return response.textArrayBuffer; return response.textArrayBuffer;
}) })
.then((buffer) => { .then(async (buffer) => {
ClipboardUtil.writeImage(buffer); const tempFilePath = this.getPicGoTempFilePath(filename, context);
}).then(() => { try {
return this.uploadClipboardFile(context); await this.fileHandler.creatAttachmentWithData(tempFilePath.relativePath, buffer);
return await this.uploadClipboardFile(context, tempFilePath.absolutePath);
} finally {
await this.fileHandler.deleteFile(tempFilePath.relativePath);
}
}).then((data) => { }).then((data) => {
if (data.success) { if (data.success) {
return {success: true, error: '', filepath: HttpUtil.extractURLFromString(data.result[0])}; return {success: true, error: '', filepath: HttpUtil.extractURLFromString(data.result[0])};
@ -87,9 +90,23 @@ export default class NetFileHandler {
} }
async uploadClipboardFile(context:HandleContext): Promise<ResultI> { private getPicGoTempFilePath(filename: string, context: HandleContext) {
const tempFileName = `${Date.now()}_${filename}`;
const relativePath = FileUtil.join(this.fileHandler.getTmpPath(), tempFileName);
// @ts-ignore
const adapter = context.plugin.app.vault.adapter;
// @ts-ignore
const basePath = adapter && adapter.getBasePath ? adapter.getBasePath() : this.fileHandler.getRootPath();
return {
relativePath: relativePath,
absolutePath: FileUtil.join(basePath, relativePath),
};
}
async uploadClipboardFile(context:HandleContext, filePath?: string): Promise<ResultI> {
const body = filePath ? JSON.stringify({list: [filePath]}) : null;
const response = await HttpUtil.httpRequest( const response = await HttpUtil.httpRequest(
context.settings.pictureBedSetting.url, {}, context.plugin.settingsManager, {method: "post"}); context.settings.pictureBedSetting.url, {}, context.plugin.settingsManager, {method: "post", body: body});
const data = response.textJson as ResultI; const data = response.textJson as ResultI;
return data; return data;
} }
@ -107,5 +124,3 @@ export default class NetFileHandler {
} }
} }

@ -7,6 +7,19 @@ import {HttpResponse} from "./model/HttpResponse";
export default class HttpUtil { export default class HttpUtil {
private static readonly IMAGE_REQUEST_HEADERS_TO_DROP = new Set([
'authority',
'content-length',
'content-type',
'host',
'origin',
'referer',
'sec-fetch-dest',
'sec-fetch-mode',
'sec-fetch-site',
'sec-fetch-user',
]);
/** /**
@ -60,6 +73,42 @@ export default class HttpUtil {
} }
} }
public static buildImageRequestHeaders(headers: Record<string, any> = {}, referer?: string, imageUrl?: string): Record<string, string> {
const nextHeaders: Record<string, string> = {};
let currentReferer = '';
Object.entries(headers || {}).forEach(([key, value]) => {
if (value == null || value === '') {
return;
}
const lowerKey = key.toLowerCase();
if (lowerKey === 'referer') {
currentReferer = String(value);
return;
}
if (this.IMAGE_REQUEST_HEADERS_TO_DROP.has(lowerKey) || lowerKey.startsWith('sec-ch-ua')) {
return;
}
nextHeaders[key] = String(value);
});
const finalReferer = referer || currentReferer || this.getDefaultImageRequestReferer(imageUrl);
if (finalReferer) {
nextHeaders.Referer = finalReferer;
}
return nextHeaders;
}
private static getDefaultImageRequestReferer(imageUrl?: string): string {
if (!imageUrl) {
return '';
}
try {
const url = new URL(imageUrl);
return `${url.protocol}//${url.host}/`;
} catch (error) {
return '';
}
}
public static parse(url: string): { protocol: string, host: string, port: string, path: string } { public static parse(url: string): { protocol: string, host: string, port: string, path: string } {
const regex = /^(.*?):\/\/([^\/:]+)(?::(\d+))?([^?]*)$/; const regex = /^(.*?):\/\/([^\/:]+)(?::(\d+))?([^?]*)$/;
@ -91,10 +140,10 @@ export default class HttpUtil {
* @param str * @param str
*/ */
public static extractURLFromString(str: string): string { public static extractURLFromString(str: string): string {
const urlRegex = /(?:!\[.*?\]\()?(https?:\/\/[^\s)]+)/g; const urlRegex = /(?:!\[.*?\]\()?(https?:\/\/[^\s)]+)/;
const matches = str.match(urlRegex); const matches = urlRegex.exec(str);
if (matches && matches.length > 0) { if (matches && matches[1]) {
return matches[0]; return matches[1];
} }
return str; return str;
} }