Skip to content

Uploading image for iOS returns responseCode -1 and response null #214

Closed
@nickdekkers

Description

@nickdekkers

Make sure to check the demo app(s) for sample usage

The demo app does not cover this problem

Make sure to check the existing issues in this repository

No related issues

If the demo apps cannot help and there is no issue for your problem, tell us about it

When I want to upload an image on an iOS simulator the plugin, in the complete method, returns a responseCode -1 and a response null. Whereas on Android the same functionality returns a responseCode 200 and a response {}. So on Android it is working fine, but on iOS it returns an error.

Uploading an image on an iOS simulator will return the following error:

 null is not an object (evaluating 'result.response.allHeaderFields')

After investigation it turns out that the background-http.ios.js file has an onError function in which it will return a responseCode of -1 and a response of null.

task.notify({
            eventName: "complete",
            object: task,
            responseCode: response ? response.statusCode : -1,
            response: response
        });

The response for some reason is null, which happens because earlier in this same function

var response = nsTask && nsTask.response ? nsTask.response : null;

sets the response to null.

My question is: How come either the nsTask or the nsTask.response is undefined?

Which platform(s) does your issue occur on?

iOS simulator

Please, provide the following version numbers that your issue occurs with:

  • CLI: 5.3.1
  • Cross-platform modules: 5.3.1
  • Runtime(s): Android 5.3.1 & iOS 5.3.1
  • Plugin(s):
    "dependencies": {
    "@angular/animations": "~7.2.0",
    "@angular/common": "~7.2.0",
    "@angular/compiler": "~7.2.0",
    "@angular/core": "~7.2.0",
    "@angular/forms": "~7.2.0",
    "@angular/http": "~7.2.0",
    "@angular/platform-browser": "~7.2.0",
    "@angular/platform-browser-dynamic": "~7.2.0",
    "@angular/router": "~7.2.0",
    "@ngx-translate/core": "~11.0.0",
    "js-yaml": "3.12.0",
    "markdown": "^0.5.0",
    "moment": "2.22.2",
    "moment-range": "4.0.1",
    "nativescript-angular": "~7.2.3",
    "nativescript-app-center": "1.0.3",
    "nativescript-appversion": "1.4.1",
    "nativescript-background-http": "3.3.0",
    "nativescript-barcodescanner": "^3.0.2",
    "nativescript-image-filters": "2.2.0",
    "nativescript-imagepicker": "6.0.4",
    "nativescript-intl": "3.0.0",
    "nativescript-iqkeyboardmanager": "1.3.0",
    "nativescript-mediafilepicker": "1.0.7",
    "nativescript-ngx-fonticon": "4.2.0",
    "nativescript-platform-css": "1.6.6",
    "nativescript-ripple": "2.1.0",
    "nativescript-social-share": "1.5.0",
    "nativescript-status-bar": "1.1.1",
    "nativescript-store-update": "1.0.2",
    "nativescript-toasty": "^1.3.0",
    "nativescript-ui-listview": "^5.1.1",
    "nativescript-ui-sidedrawer": "^5.1.0",
    "nativescript-vibrate": "2.1.1",
    "nativescript-videoplayer": "4.2.0",
    "nativescript-web-image-cache": "~5.0.0",
    "reflect-metadata": "0.1.12",
    "rxjs": "^6.3.3",
    "tns-core-modules": "~5.3.1",
    "zone.js": "^0.8.4"
    },
    "devDependencies": {
    "@angular-devkit/build-angular": "^0.11.3",
    "@angular/compiler-cli": "~7.2.0",
    "@types/chai": "4.1.4",
    "@types/mocha": "5.2.5",
    "@types/moment-range": "3.1.0",
    "@types/sinon": "5.0.2",
    "@types/sinon-chai": "3.2.0",
    "babel-traverse": "6.26.0",
    "babel-types": "6.26.0",
    "babylon": "6.18.0",
    "chai": "4.1.2",
    "chai-moment": "^0.1.0",
    "lazy": "1.0.11",
    "mocha": "5.2.0",
    "nativescript": "~5.3.1",
    "nativescript-dev-sass": "~1.6.1",
    "nativescript-dev-typescript": "~0.9.0",
    "nativescript-dev-webpack": "~0.21.0",
    "node-sass": "^4.11.0",
    "sinon": "6.1.5",
    "sinon-chai": "3.2.0",
    "tns-platform-declarations": "~5.2.0",
    "ts-node": "~8.0.2",
    "typescript": "~3.1.1"
    }

Please, tell us how to recreate the issue in as much detail as possible.

Create a simple app where you use the imagepicker to retrieve an image from the iOS simulator and upload that image using this plugin.

Is there any code involved?

upload(apiUrl: string, filepath: string, filename: string, progressSubscriber?: Subscriber<IFileUploadProgress>): Observable<HttpResponse<any>> {
        apiUrl = this.apiUrlAppender.appendUrl(apiUrl);

        return new Observable<HttpResponse<any>>(subscriber => {
            const session = bghttp.session("image-upload");
            const request = <Request> {
                url: apiUrl,
                method: "POST",
                headers: {
                    "Content-Type": "application/octet-stream",
                    "Authorization": this.authorizationContext.getToken().getHeaderValue()
                },
                description: ''
            };

            const params = [
                { name: filename, filename: filepath }
            ];

            const task = session.multipartUpload(params, request);

            if (progressSubscriber) {
                task.on('progress', (result: any) => {
                    this.zone.run(() => {
                        progressSubscriber.next(result);
                    });
                });
            }

            task.on("error", (result) => {
                this.zone.run(() => {
                    subscriber.error(result.error);
                })
            });

            let iosResponse: string;

            if (isIOS) {
                task.on('responded', (result) => {
                    if (result.responseCode >= 300) {
                        subscriber.error("Got response code: " + result.responseCode);
                    }
                    iosResponse = result.data;
                });
            }

            task.on('complete', (result: any) => {
                if (subscriber.closed) {
                    return;
                }

                let headers = new HttpHeaders();

                if (isAndroid) {
                    const iterator = result.response.getHeaders().entrySet().iterator();
                    while (iterator.hasNext()) {
                        const header = iterator.next();
                        headers = headers.append(header.getKey, header.getValue());
                    }
                } else if (isIOS) {
                    console.dir(result.response.allHeaderFields);
                }

                const response = new HttpResponse({
                    body: JSON.parse(iosResponse || result.response.getBodyAsString()),
                    headers,
                    status: result.responseCode,
                    url: apiUrl
                });

                this.zone.run(() => {
                    if (progressSubscriber) {
                        progressSubscriber.complete();
                    }

                    if (result.responseCode == 200) {
                        subscriber.next(response);
                    } else {
                        subscriber.error(response);
                    }

                    subscriber.complete();
                });
            })
        })
        .pipe(map(x => x.body))
    }

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions