export default class UploadAdapter { constructor(loader, options) { this.loader = loader; this.options = options; this.timeout = 60000; // 60秒超时 } upload() { return this.loader.file.then( (file) => new Promise((resolve, reject) => { this._initRequest(); this._initListeners(resolve, reject, file); this._sendRequest(file); this._initTimeout(reject); }), ); } abort() { if (this.xhr) { this.xhr.abort(); } if (this.timeoutId) { clearTimeout(this.timeoutId); } } _initRequest() { const xhr = (this.xhr = new XMLHttpRequest()); xhr.open("POST", this.options.upload.uploadUrl, true); xhr.responseType = "json"; } _initListeners(resolve, reject, file) { const xhr = this.xhr; const loader = this.loader; const genericErrorText = `Couldn't upload file: ${file.name}.`; xhr.addEventListener("error", () => { console.error("[UploadAdapter] Upload error for file:", file.name); reject(genericErrorText); }); xhr.addEventListener("abort", () => { console.warn("[UploadAdapter] Upload aborted for file:", file.name); reject(); }); xhr.addEventListener("timeout", () => { console.error("[UploadAdapter] Upload timeout for file:", file.name); reject(`Upload timeout: ${file.name}. Please try again.`); }); xhr.addEventListener("load", () => { const response = xhr.response; // 检查响应状态码 if (xhr.status >= 200 && xhr.status < 300) { if (!response) { console.error("[UploadAdapter] Empty response for file:", file.name); reject(genericErrorText); return; } // 检查业务状态码(假设 code=1 表示成功) if (response.code == 1 || response.code == undefined) { const url = response.data?.url || response.data?.src; if (!url) { console.error("[UploadAdapter] No URL in response for file:", file.name, response); reject("Upload succeeded but no URL returned"); return; } resolve({ default: url }); } else { const errorMessage = response.message || genericErrorText; console.error("[UploadAdapter] Upload failed for file:", file.name, "Error:", errorMessage); reject(errorMessage); } } else { console.error("[UploadAdapter] HTTP error for file:", file.name, "Status:", xhr.status); reject(`Server error (${xhr.status}): ${file.name}`); } }); // 上传进度监听 if (xhr.upload) { xhr.upload.addEventListener("progress", (evt) => { if (evt.lengthComputable) { loader.uploadTotal = evt.total; loader.uploaded = evt.loaded; } }); } } _initTimeout(reject) { // 清除之前的超时定时器(如果有) if (this.timeoutId) { clearTimeout(this.timeoutId); } // 设置新的超时定时器 this.timeoutId = setTimeout(() => { if (this.xhr) { this.xhr.abort(); reject(new Error("Upload timeout")); } }, this.timeout); } _sendRequest(file) { // 设置请求超时 this.xhr.timeout = this.timeout; // Set headers if specified. const headers = this.options.upload.headers || {}; const extendData = this.options.upload.extendData || {}; // Use the withCredentials flag if specified. const withCredentials = this.options.upload.withCredentials || false; const uploadName = this.options.upload.uploadName || "file"; for (const headerName of Object.keys(headers)) { this.xhr.setRequestHeader(headerName, headers[headerName]); } this.xhr.withCredentials = withCredentials; const data = new FormData(); for (const key of Object.keys(extendData)) { data.append(key, extendData[key]); } data.append(uploadName, file); this.xhr.send(data); } } export function UploadAdapterPlugin(editor) { editor.plugins.get("FileRepository").createUploadAdapter = (loader) => { return new UploadAdapter(loader, editor.config._config); }; }