You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nativescript Angular iOS上传文件遇NSURLErrorDomain Code=-1001超时求助

解决NativeScript Angular iOS低速网络上传超时问题

针对NSURLErrorDomain Code=-1001请求超时错误,可通过以下几种方案解决:

1. 延长HTTP请求超时时间

Angular HttpClient默认超时较短,低速网络下上传大文件容易触发超时,可通过RxJS的timeout操作符为单个请求设置更长超时:

import { timeout } from 'rxjs/operators';

upload(photosData: PhotoWrapper): Observable<PhotoResult> {
    let headers = this.authService.getAuthHeader();
    // 设置5分钟超时(300000毫秒),根据实际需求调整
    const timeoutMs = 300000;

    return this.http.post<boolean>(this.configurationService.uploadPhotoUrl(), photoDto, { headers: headers, observe: 'response' })
        .pipe(
            timeout(timeoutMs),
            map((result)=>( {flag: result.body, wrapper: photosData} as PhotoResult))
        );
}

2. 限制并发上传数量

当前代码使用zip和forkJoin同时上传所有文件,低速网络下并发过多会分摊带宽,导致单个请求超时。可改用mergeMap限制并发数,比如一次仅上传2个文件:

// 替换uploadPhotos方法中的zip逻辑
import { from } from 'rxjs';
import { mergeMap, scan } from 'rxjs/operators';

// ...

if (this.photos !== null && this.photos.length > 0) {
    const photosList$ = new Array<Observable<boolean[]>>;

    this.photos.forEach(photo=> {
        const observable = this.submitPhoto(photo)
        if (observable) {
            photosList$.push(observable);
        }
    });

    from(photosList$).pipe(
        mergeMap(obs => obs, 2), // 限制同时上传2个文件
        scan((acc, current) => {
            // 累计上传失败和成功数量
            acc[0] += current.filter(f => !f).length;
            acc[1] += current.filter(f => f).length;
            return acc;
        }, [0, 0])
    ).subscribe(([notuploaded, uploaded]) => {
        this.message = `Uploaded ${uploaded} Photo(s).`;
        if (notuploaded > 0) {
            this.message += ` Errors uploading ${notuploaded}`;
        }
    });
}

3. 添加超时重试机制

针对临时网络波动导致的超时,可通过retryWhen操作符实现重试逻辑,避免单次超时直接失败:

import { timeout, retryWhen, delay, scan } from 'rxjs/operators';

upload(photosData: PhotoWrapper): Observable<PhotoResult> {
    let headers = this.authService.getAuthHeader();
    const timeoutMs = 300000;
    const maxRetries = 2; // 最多重试2次

    return this.http.post<boolean>(this.configurationService.uploadPhotoUrl(), photoDto, { headers: headers, observe: 'response' })
        .pipe(
            timeout(timeoutMs),
            retryWhen(errors => 
                errors.pipe(
                    scan((retryCount) => {
                        if (retryCount >= maxRetries) {
                            throw new Error('Max retries exceeded');
                        }
                        return retryCount + 1;
                    }, 0),
                    delay(1000) // 重试前延迟1秒,给网络恢复时间
                )
            ),
            map((result)=>( {flag: result.body, wrapper: photosData} as PhotoResult))
        );
}

4. 优化文件上传格式,避免Base64转码

Base64会使文件体积增大30%,大幅增加上传时间。改用FormData直接上传二进制文件,减少数据传输量:

upload(photosData: PhotoWrapper): Observable<PhotoResult> {
    let headers = this.authService.getAuthHeader();
    // 移除手动设置的Content-Type,让客户端自动处理multipart/form-data边界
    headers.delete('Content-Type');
    
    const formData = new FormData();
    // 直接添加本地文件到FormData(假设photosData.File是NativeScript的File对象)
    formData.append('photo', photosData.File, photosData.File.name);
    // 如需上传元数据,可添加JSON字段
    formData.append('photoMetadata', JSON.stringify({
        id: photosData.id,
        uploaded: photosData.Uploaded
    }));

    const timeoutMs = 300000;

    return this.http.post<boolean>(this.configurationService.uploadPhotoUrl(), formData, { headers: headers, observe: 'response' })
        .pipe(
            timeout(timeoutMs),
            map((result)=>( {flag: result.body, wrapper: photosData} as PhotoResult))
        );
}

5. iOS原生层面调整NSURLSession超时

NativeScript底层依赖iOS的NSURLSession,可全局配置更长的超时时间:

import { ios } from '@nativescript/core';

// 在应用初始化时(比如app.ts)添加以下代码
if (ios) {
    const sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration();
    // 设置单个请求超时(秒)
    sessionConfig.timeoutIntervalForRequest = 300; // 5分钟
    // 设置整个资源传输的超时(秒)
    sessionConfig.timeoutIntervalForResource = 600; // 10分钟
    // 替换默认的URLSession
    NSURLSession.sharedSession = NSURLSession.sessionWithConfigurationDelegateDelegateQueue(sessionConfig, null, null);
}

建议组合使用上述方案,比如二进制上传+延长超时+限制并发+重试,能最大程度降低低速网络下的超时概率。

内容的提问来源于stack exchange,提问作者Pein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 11:27:42