0

To explain what I want to do, I want the user:

Workflow:

  1. to be able to upload files to Firebase storage,
  2. The detail of that file is stored in Firestore using .set(),
  3. user see the name of the file on text input (loads from Firestore) and the user can download the file

No. (1) and (3) I have successfully done it, except no. (2). The doc itself, which contain the detail of the uploaded file, is not there in the Firestore. No errors show up that say it is failed to add the docs to Firestore, only just a warning like the attached image below.

Connection WebChannel transport errored

To add, yesterday, I already deploy an update of the same workflow for my live web app, on one of the pages, (Let's say: Page A). It works as I wanted, from (1) to (3). Now I want to do the same workflow on other pages, (e.g. Page B, C, etc).

Today, on the localhost, on any part of my app including Page A, my app cannot add a doc of the uploaded file into Firestore. But when I do it on the live web app, it works and it still is.

Already gone through the internet and there are almost the same questions as me, but none of them works for me. Any advice?

HTML part

<v-row style="margin-left: 1%;">
    <v-col cols="12" sm="6" md="12">
        <h2>Program Summary</h2>
        <h4>Upload the program summary of the package here.</h4>
    </v-col>
</v-row>
<v-row style="margin-left: 1%;" v-if="fileUploaded">
    <v-col cols="12" sm="6" md="4">
        <v-text-field
            v-model="editedItem.fileName"
            outlined
            readonly></v-text-field>
    </v-col>
    <v-col cols="12" sm="6" md="3">
        <v-btn
            color="yellow"
            dark
            medium
            style="margin: 0.5rem;"
            @click.prevent="downloadFile()">
                View
        </v-btn>
    </v-col>
</v-row>
<v-row style="margin-left: 1%;" v-else>
    <v-col cols="12" sm="6" md="4">
        <v-file-input
            outlined
            show-size
            prepend-icon="null"
            accept=".pdf"
            v-model="ProgramSummary"
            :disabled="processing">
                <template v-slot:append-outer>
                    <v-progress-circular
                        v-if="processing"
                        indeterminate
                        color="red">
                    </v-progress-circular>
                </template>
        </v-file-input>
    </v-col>
    <v-col cols="12" sm="6" md="3">
        <v-btn
            color="primary"
            dark
            style="margin: 0.5rem;"
            @click.prevent="uploadProgramSummary()">
                Upload
        </v-btn>
    </v-col>
</v-row>

upload file and add detail of file into Firestore

// SAVE UPLOADED FILE TO FIRESTORE
onUpload() {
    var uidRef = firebase.auth().currentUser.uid;
    //var docName = `${this.ProgramSummary.name}`;
    var docRef = firestore
                    .collection("SubworkPackage")
                    .doc(firebase.auth().currentUser.uid)
                    .collection("ProgramSummary")
                    .doc();
    var data = {
        fileName: this.ProgramSummary,  // <--- this get the file name to firestore
        uid: uidRef,
        id: docRef,
    };
    firestore
        .collection("SubworkPackage")
        .doc(firebase.auth().currentUser.uid)
        .collection("ProgramSummary")
        .doc(firebase.auth().currentUser.uid)
        .set(data);
},

// PROGRAM SUMMARY UPLOAD FILE
uploadProgramSummary() {
    //LOADING ICON SET TO TRUE
    this.processing = true;
    //DOC REFERENCE OF USER ID
    var uidRef = firebase.auth().currentUser.uid;
    // DOC NAME IS SET TO HAVE A FIXED NAME
    var programSummaryRef = "ProgramSummary.pdf";
    // FILE PATH
    var filePath = `WorkPackageContractor/${uidRef}/${programSummaryRef}`;
    var docName = `${this.ProgramSummary.name}`; 
    // METADATA
    const metadata = { contentType: this.ProgramSummary.type };
    //FIREBASE STORAGE ACTION
    FirebaseStorage
        .ref()
        .child(filePath)
        .put(this.ProgramSummary, metadata)
        .then(() => {
            FirebaseStorage
                .ref()
                .child(filePath)
                .put(this.ProgramSummary, metadata)
                .snapshot
                .ref
                .getDownloadURL()
                .then(() => { // url
                    //this.ProgramSummary = url;
                    this.ProgramSummary = docName;
                    this.onUpload();
                    this.processing = false;
                    alert("Program Summary Succesfully Uploaded!")
                    window.location.reload();
                })
        })
},

download file from Firebase Storage

downloadFile() {
    var uidRef = firebase.auth().currentUser.uid;
    var programSummaryRef = "ProgramSummary.pdf";
    var filePath = `WorkPackageContractor/${uidRef}/${programSummaryRef}`;
    const fileRef = FirebaseStorage.ref().child(filePath);
    fileRef
        .getDownloadURL()
        .then((url) => {
            console.log(url);
            const xhr = new XMLHttpRequest();
            xhr.responseType = 'blob';
            xhr.onload = function() {
                const blob = xhr.response;
                const link = document.createElement('a');
                link.href = URL.createObjectURL(blob);
                link.download = "Program Summary";
                link.click();
                URL.revokeObjectURL(link.href);
            };
            xhr.open('GET', url);
            xhr.send();
        }).catch((error) => {
            // Handle any errors
            switch (error.code) {
            case 'storage/object-not-found':
                // File doesn't exist
                break;

            case 'storage/unauthorized':
                // User doesn't have permission to access the object
                break;

            case 'storage/canceled':
                // User canceled the upload
                break;

            case 'storage/unknown':
                // Unknown error occurred, inspect the server response
                break;
            default:
                break;
            }
        });
},

Read uploaded file detail from Firestore, inside created(),

readFileInput() {
    let _this = this;
    firestore
        .collection("SubworkPackage")
        .doc(firebase.auth().currentUser.uid)
        .collection("ProgramSummary")
        .doc(firebase.auth().currentUser.uid)
        .get()
        .then(doc => {
            if (doc.exists) {
                _this.fileUploaded = true;
                _this.editedItem.fileName = doc.data().fileName
            } else {
                _this.fileUploaded = false;
                console.log("No Document Exists");
            }
        })
},

Notes:

  1. I want the detail of the uploaded file to be added in Firestore after the file is uploaded.
  2. I'm using Nuxt.js v2 and Firebase v8.10.0
  3. It works on my live hosting web app but not on the localhost (I want to deploy the latest today update to see if it really happens just on localhost, but nope, I dont want for it to broke my current live hosting web app too if anything went wrong).
  4. Already tried experimentalForceLongPolling , experimentalAutoDetectLongPolling , useFetchStreams. still not working.

1 Answers1

0

Found how to solve it. Rookie mistake.

The page is reloaded first before the document can be added to the Firestore.

To fix this,

this.processing = false;  // loading icon
alert("Program Summary is succesfully Uploaded!") // alert box
window.location.reload()  // page refresh

is put inside .then() of onUpload() function instead of inside UploadProgramSummary(). This is so that the document can be completely stored first before the page is reloaded.

  • Add uploaded file detail to Firestore
// SAVE UPLOADED FILE TO FIRESTORE
onUpload() {
    var uidRef = firebase.auth().currentUser.uid;
    //var docName = `${this.ProgramSummary.name}`;
    var docRef = firestore
                    .collection("SubworkPackage")
                    .doc(firebase.auth().currentUser.uid)
                    .collection("ProgramSummary")
                    .doc();
    var data = {
        fileName: this.ProgramSummary,  // <--- this get the file name to firestore
        uid: uidRef,
        id: docRef,
    };
    firestore
        .collection("SubworkPackage")
        .doc(firebase.auth().currentUser.uid)
        .collection("ProgramSummary")
        .doc(firebase.auth().currentUser.uid)
        .set(data)
        .then(() => {
            this.processing = false;
            alert("Program Summary Succesfully Uploaded!")
            window.location.reload();
        })
},
  • Add file to Firebase Storage
// PROGRAM SUMMARY UPLOAD FILE
uploadProgramSummary() {
    //LOADING ICON SET TO TRUE
    this.processing = true;
    //DOC REFERENCE OF USER ID
    var uidRef = firebase.auth().currentUser.uid;
    // DOC NAME IS SET TO HAVE A FIXED NAME
    var programSummaryRef = "ProgramSummary.pdf";
    // FILE PATH
    var filePath = `WorkPackageContractor/${uidRef}/${programSummaryRef}`;
    var docName = `${this.ProgramSummary.name}`; 
    // METADATA
    const metadata = { contentType: this.ProgramSummary.type };
    //FIREBASE STORAGE ACTION
    FirebaseStorage
        .ref()
        .child(filePath)
        .put(this.ProgramSummary, metadata)
        .then(() => {
            FirebaseStorage
                .ref()
                .child(filePath)
                .put(this.ProgramSummary, metadata)
                .snapshot
                .ref
                .getDownloadURL()
                .then(() => { // url
                    //this.ProgramSummary = url;
                    this.ProgramSummary = docName;
                    this.onUpload();
                })
        })
},