简体   繁体   中英

Converting working Ajax call to Angular Observable

I have an existing JavaScript application that submits documents (.pdf, .txt...) to Solr for text extraction. I am now trying to convert that capability to an Angular-6 implementation and am struggling with the whole observable pattern. Below is the working js code, followed by my angular component and service .ts files. I think I'm close, but no cigar.

let myReader = new FileReader();

    myReader.onloadend = function() {
        fileAsBlob = myReader.result;

        sendToSolr(fileAsBlob); 
    };
    fileAsBlob = myReader.readAsArrayBuffer(file);
    /* Get the unique Id for the doc and append to the extract url*/
    let docId = $("#post_docId").val();
    let extractUrl = "http://localhost:8983/solr/" + core + "/update/extract/?commit=true&literal.id=" + docId;


    /* Ajax call to Solr/Tika to extract text from pdf and index it */
    function sendToSolr(fileAsBlob) {
        $.ajax({ 
            url: extractUrl,
            type: 'POST',
            data: fileAsBlob,
            cache: false,
            jsonp: 'json.wrf',
            processData: false,
            contentType: false, 
            echoParams: "all",

            success: function(data, status) {
                //console.log("Ajax.post successful, status: " + data.responseHeader.status + "\t status text: " + status);
                //console.log("debug");
                getDocument(docId);
            },
            error: function(data, status) {
                //console.log("Ajax.post error, status: " + data.status + "\t status text:" + data.statusText);
            },
            done: function(data, status) {
                //console.log("Ajax.post Done");
            },
        });
    }

All the above does is use a fileReader to read a local file into an ArrayBuffer, and submits that ArrayBuffer to Solr via an Ajax call. In my success I do call another function (getDocument) which just queries Solr (By docId) for the document I just submitted and displays it. Not beautiful, but it works.

For the angular version I have the following service:

constructor(private http: HttpClient) { }

postDocToSolr(fileAsBlob: any): Observable<any> {
    let httpHeaders = new HttpHeaders()
    .set('type' , 'POST')
    .set('jsonp', 'json.wrf')
    .set('processData', 'false')
    .set('echoParams', 'all')
    .set('Content-Type', 'application/x-www-form-urlencoded')
    .set('charset', 'utf-8')
    .set('data', fileAsBlob);

    let options = {
        headers: httpHeaders
    };




    return this.http.post(this.extractUrl, fileAsBlob, options);

}

}

I tried posting the entire service, but it threw the formatting off so here is the POST part of the service.

And in my component I call the service:

    extractText(fileContents: any) {
    console.log("In the Document.extractText() method");
    //this.processDocument(fileContents);
    this.textExtractor.postDocToSolr(fileContents)
    .subscribe(data => {
        console.log("Debug");
        console.log("Data: ") + data;
    },
    error => {
        console.log("Error" + error);
    }
    );
    console.log("Debug");
}

Note I've done the fileReader already and am submitting basically the same ArrayBuffer.

The only hint is the in the error => log the error callback(Right term?)on the observable. I get an error code 400, bad request with the message: "msg":"URLDecoder: Invalid digit (P) in escape (%) pattern" Which doen't help me much. I'm wondering if it's an encoding issue (UTF-8) but not sure where to begin. Would appreciate a nudge in the right direction.

It looks like the problem is how angular is encoding your URI, I would open your network tool of choice (network tab, fiddler, etc) and look at the sent request URI of each. I suspect they'll be different.

Well, it's often the small things that trip me up. I needed to set the Content-Type to "false" and everything works fine. I also re-did the creation of the httpHeaders, but I think either way would have worked. The working postToSolr Service method is:

export class TextExtractorServiceService {
extractUrl: string = "http://localhost:8983/solr/tater/update/extract/?commit=true&literal.id=778";

constructor(private http: HttpClient) { }

postDocToSolr(fileAsBlob: any): Observable<any> {
    const httpOptions = {
        headers: new HttpHeaders({
            "jsonp": "json.wrf",
            "processData": "false",
            "echoParams" : "all",
            "Content-Type": "false",
            "cache": "false"
        })
    };

    return this.http.post(this.extractUrl, fileAsBlob, httpOptions);

}

}

Thanks to all who took a look.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM