yikart/AiToEarn · info · DOMException

上传已取消

Error message

上传已取消

What it means

optimizeImageForUpload honors an AbortSignal so callers can cancel pre-upload image optimization. If options.signal.aborted is already true when the function starts, it throws DOMException('上传已取消', 'AbortError') instead of doing wasted compression work.

Source

Thrown at project/aitoearn-web/src/utils/media.ts:159

  if (typeof File === 'undefined')
    return null

  if (file instanceof File)
    return file

  return new File([file], getUploadImageFileName(file), {
    type: getCompressionFileType(file.type),
    lastModified: Date.now(),
  })
}

/** 上传前优化图片:超过 1MB 的 jpeg/png/webp 会限制最长边并尽量压缩到 1MB 内 */
export async function optimizeImageForUpload(file: File | Blob, options?: OptimizeImageForUploadOptions) {
  if (!shouldOptimizeImageForUpload(file) || typeof window === 'undefined')
    return file

  if (options?.signal?.aborted)
    throw new DOMException('上传已取消', 'AbortError')

  const compressionFile = toImageCompressionFile(file)
  if (!compressionFile)
    return file

  try {
    const { default: imageCompression } = await import('browser-image-compression')
    const compressionOptions: ImageCompressionOptions = {
      maxSizeMB: IMAGE_UPLOAD_MAX_SIZE_MB,
      maxWidthOrHeight: IMAGE_UPLOAD_MAX_WIDTH_OR_HEIGHT,
      initialQuality: IMAGE_UPLOAD_INITIAL_QUALITY,
      useWebWorker: false,
      fileType: getCompressionFileType(compressionFile.type),
      signal: options?.signal,
    }
    const compressedFile = await imageCompression(compressionFile, compressionOptions)

    return compressedFile.size < file.size ? compressedFile : file

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Treat DOMException with name 'AbortError' as an expected cancellation: swallow it or update UI to 'cancelled', don't show it as an error
  2. Check signal.aborted in the caller before invoking uploadFile if cancellation is possible
  3. Create a fresh AbortController for each upload instead of reusing an already-aborted one

Example fix

// before
await uploadFile(file, { signal: controller.signal }) // throws if already aborted
// after
if (!controller.signal.aborted) {
  await uploadFile(file, { signal: controller.signal })
}
Defensive patterns

Strategy: try-catch

Validate before calling

function canStartUpload(signal?: AbortSignal): boolean {
  return !signal?.aborted
}

Type guard

function isAbortError(e: unknown): e is DOMException {
  return e instanceof DOMException && e.name === 'AbortError'
}

Try / catch

try {
  await uploadFile(file, { signal })
} catch (e) {
  if (isAbortError(e)) { markUploadCancelled(file); return } // expected cancellation
  throw e
}

Prevention

When it happens

Trigger: Calling optimizeImageForUpload (directly or via uploadFile) with an AbortSignal that was aborted before the call — e.g. user cancelled the upload, component unmounted, or a timeout fired before optimization began.

Common situations: User removes a file from an upload queue while it is pending, a React effect aborts on unmount, or an overall upload deadline aborts the controller at the optimization stage.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/8b2091d0494950e9. Report an issue: GitHub.