0

I have a little REST API which takes two PDF's and returns a comparison URL from the Draftable API. The API has been tested and works fine. As I'm new to REST API's and Angular I have problems figuring out how to send two PDF's to the API.

This is how I've tested my API: enter image description here

The part of API:

@PostMapping("/draftableDemo")
    String compareJob(@RequestParam("file1") MultipartFile file1, @RequestParam("file2") MultipartFile file2) {
        CompareJob compareJob = new CompareJob(convert(file1), convert(file2));
        DraftableCompare draftableCompare = new DraftableCompare();
        return draftableCompare.compare(compareJob);
    }

I've found this SO post which had similar issues as I'm having.

  • How do I define the two PDF's on the Angular side with their representing keys?
  • Do I have to change what my API is expecting?
  • I'm always reading of a Angular file uploader, which Module is everyone talking about?

Thanks for any hints, ideas or suggestions!

EDIT: My HTML:

<div class="content"
     fxLayout="row"
     fxLayout.xs="column"
     fxFlexFill>

    <div fxFlex="50" fxFlex.xs="50" style="position: relative">
        <div>
            <div>
                <p>
                    Open first PDF
                </p>
                <input (change)="onFileSelected(pdf1)" type="file" [multiple]="multiple" id="file1">
            </div>

            <div *ngIf="error" class="error mb">
                {{ error.message | json }}
            </div>

            <div *ngIf="!isLoaded && !error && progressData" id="progress1">
                <div class="bg">
                    <div class="bar" [style.width]="progressData.loaded / progressData.total * 100 + '%'"></div>
                </div>
                <span>{{ getInt(progressData.loaded / progressData.total * 100) }}%</span>
            </div>

            <pdf-viewer [src]="pdfSrc1"
                        [(page)]="page"
                        [rotation]="rotation"
                        [original-size]="originalSize"
                        [fit-to-page]="fitToPage"
                        (after-load-complete)="afterLoadComplete($event)"
                        [zoom]="zoom"
                        [show-all]="showAll"
                        [stick-to-page]="stickToPage"
                        [render-text]="renderText"
                        [external-link-target]="'blank'"
                        [autoresize]="autoresize"
                        [render-text-mode]="renderTextMode"
                        (error)="onError($event)"
                        (on-progress)="onProgress($event)"
                        (page-rendered)="pageRendered($event)"
            ></pdf-viewer>
        </div>
    </div>

    <div fxFlex="50" style="position: relative">
        <div>
            <div>
                <p>
                    Open second PDF
                </p>
                <input (change)="onFileSelected(pdf2)" type="file" [multiple]="multiple" id="file2">
            </div>

            <div *ngIf="error" class="error mb">
                {{ error.message | json }}
            </div>

            <div *ngIf="!isLoaded && !error && progressData" id="progress2">
                <div class="bg">
                    <div class="bar" [style.width]="progressData.loaded / progressData.total * 100 + '%'"></div>
                </div>
                <span>{{ getInt(progressData.loaded / progressData.total * 100) }}%</span>
            </div>


            <pdf-viewer [src]="pdfSrc2"
                        [(page)]="page"
                        [rotation]="rotation"
                        [original-size]="originalSize"
                        [fit-to-page]="fitToPage"
                        (after-load-complete)="afterLoadComplete($event)"
                        [zoom]="zoom"
                        [show-all]="showAll"
                        [stick-to-page]="stickToPage"
                        [render-text]="renderText"
                        [external-link-target]="'blank'"
                        [autoresize]="autoresize"
                        [render-text-mode]="renderTextMode"
                        (error)="onError($event)"
                        (on-progress)="onProgress($event)"
                        (page-rendered)="pageRendered($event)"
            ></pdf-viewer>
        </div>
    </div>

</div>




<hr>
<input type="file" [multiple]="multiple" #fileInput>
<file-upload #fu (change)="fu.upload()" [multiple]="true"></file-upload>
<div class="example-button-row">
    <button mat-raised-button color="primary" routerLink="/draftable" (click)="compareDraftable()">Draftable</button>
    <button mat-raised-button color="primary" routerLink="/pdfcompare">PDF compare</button>
    <button mat-raised-button color="primary">Version3</button>
    <button mat-raised-button color="primary">Version4</button>
</div>

And the TS:

export class MainComponent implements OnInit {
    // pdfSrc1: string | PDFSource | ArrayBuffer = './assets/fullText2Page.pdf';
    // pdfSrc2: string | PDFSource | ArrayBuffer = './assets/fullText1Page.pdf';

    leftFile: File = null;
    rightFile: File = null;

    @Input() multiple = true;
    @ViewChild('fileInput') inputEl: ElementRef;

    constructor(private http: HttpClient) {
    }

    pdfSrc1: string | PDFSource | ArrayBuffer = '';
    pdfSrc2: string | PDFSource | ArrayBuffer = '';

    pdf1 = 'pdfSrc1';
    pdf2 = 'pdfSrc2';

    error: any;
    page = 1;
    rotation = 0;
    zoom = 1;
    originalSize = false;
    pdf: any;
    renderText = true;
    progressData: PDFProgressData;
    isLoaded = false;
    stickToPage = false;
    showAll = true;
    autoresize = true;
    fitToPage = false;
    outline: any[];
    renderTextMode = 2;

    @ViewChild(PdfViewerComponent) private pdfComponent: PdfViewerComponent;

    ngOnInit(): void {
    }



    /**
     * Render PDF preview on selecting file
     */
    onFileSelected(pdfSource) {
        console.log('Source: ', pdfSource);
        let $pdf: any;

        if (pdfSource === 'pdfSrc1') {
            $pdf = document.querySelector('#file1');
        } else {
            $pdf = document.querySelector('#file2');
        }

        if (typeof FileReader !== 'undefined') {
            const reader = new FileReader();

            reader.onload = (e: any) => {
                if (pdfSource === 'pdfSrc1') {
                    this.pdfSrc1 = e.target.result;
                } else {
                    this.pdfSrc2 = e.target.result;
                }

            };

            reader.readAsArrayBuffer($pdf.files[0]);
        }
    }

    /**
     * Get pdf information after it's loaded
     */
    afterLoadComplete(pdf: PDFDocumentProxy) {
        this.pdf = pdf;
        this.isLoaded = true;
        this.loadOutline();
    }

    /**
     * Get outline
     */
    loadOutline() {
        this.pdf.getOutline().then((outline: any[]) => {
            this.outline = outline;
        });
    }

    /**
     * Handle error callback
     */
    onError(error: any) {
        this.error = error; // set error
    }


    /**
     * Pdf loading progress callback
     */
    onProgress(progressData: PDFProgressData) {
        // console.log('Progress Data: ', progressData);
        this.progressData = progressData;
        this.isLoaded = false;
        this.error = null; // clear error
    }

    getInt(value: number): number {
        return Math.round(value);
    }

    /**
     * Page rendered callback, which is called when a page is rendered (called multiple times)
     */
    pageRendered(e: CustomEvent) {
        // console.log('(page-rendered)', e);
    }

    compareDraftable() {
        const fd = new FormData();
        fd.append('file1', this.leftFile, this.leftFile.name);
        this.http.post('localhost:8080/draftableDemo', fd)
            .subscribe(res => {
                console.log(res);
            });
    }

    upload() {
        const inputEl: HTMLInputElement = this.inputEl.nativeElement;
        const fileCount: number = inputEl.files.length;
        const formData = new FormData();
        if (fileCount > 0) { // a file was selected
            for (let i = 0; i < fileCount; i++) {
                formData.append('file[]', inputEl.files.item(i));
            }
            this.http
                .post('localhost:8080/draftableDemo', formData);
            // do whatever you do...
            // subscribe to observable to listen for response
        }
    }
In0cenT
  • 481
  • 2
  • 11
  • 25
  • What have you tried, and why the linked SO Post didn't help you? – Kepotx Mar 18 '19 at 15:24
  • Thanks for your reply. I've added the HTML and TS of the Angular project where you can see what I'm trying. What I do not understand is where does the tag come from? – In0cenT Mar 18 '19 at 16:17
  • @In0cenT: In the SO question that you linked, [accepted answer](https://stackoverflow.com/a/39862337/3850730) has an Angular Component defined - `export class FileUploadComponent` . That component has html selector defined as - `file-upload` . So when you use that tag in your html, that componet's logic will come into play. Ask further questions , if that component's logic is not making sense to you. – Sabir Khan Mar 19 '19 at 11:45
  • @In0cenT did my answer helped you? If no, could you tell why so we can keep help you? – Kepotx Mar 21 '19 at 14:07

1 Answers1

0
  • How do I define the two PDF's on the Angular side with their representing keys?

Currently, You already have two files, all you need to do is send them via a POST query

let formData:FormData = new FormData();
formData.append('file1', this.pdfSrc1);
formData.append('file2', this.pdfSrc2);

const req = new HttpRequest('POST', 'localhost:8080/draftableDemo', formData);
  • Do I have to change what my API is expecting?

As the formData send PDF files with the exact same key names as with PostMan or what API is waiting for, and unless this.pdfSrc1/this.pdfSrc2 are not at the correct format, it should be fine

  • I'm always reading of a Angular file uploader, which Module is everyone talking about?

No need of angular file uploader or tag here

Kepotx
  • 1,095
  • 12
  • 26