2

I'm trying to upload an Image with the Uploader of Quasar via apollo-upload.

<q-uploader multiple :url="url" :upload-factory="uploadFactory"/> This is 
how I implement the Uploader.

Here is the uploadFactory-Function:

uploadFactory (file, updateProgress) {

    return(

        this.$apollo.mutate({
        mutation: gql`
            mutation($file: Upload!) {
            uploadFile(file: $file) {
                filename
                }
            }
        `,
        variables: { file: file }
        })

    )
  return new Promise(resolve, reject);
},

And on the serverside I got this:

async uploadFile (parent, { file } ) {
    const { stream, filename, mimetype, encoding } = await file;

    var fs = require('fs');
    const id = 1;
    const uploadDir = __dirname;
    const path = `${uploadDir}/${filename}`
    var wstream = fs.createWriteStream(path);
    wstream.write(stream);
    wstream.end();


    return { stream, filename, mimetype, encoding };
  },
},

So far for the Code. If I enter a new Image and press the upload-Button the uploadFactory has the img-src in file.__img. If sending the data to the server the __img-Object is totally empty: {}. I tried to send the file, just the file.__img, tried to copy the value, but it is empty every time.

Has Someone achieved this? Or is it even possible?

FYI: Some links, if you haven't heared of quasar or apollo yet: Quasar Uploader, Apollo Upload

1
  • Any updates since you asked this? Commented Oct 23, 2018 at 15:40

1 Answer 1

1

I made a workaround, but it works for my needs.

Client:

<input-camera v-if="status=='S' && damage != null" ref="inputCamera" @photo="addFile" @popup="openPopup" @removePhoto="removeFile" v-bind:allowMultiple="true" v-bind:labelText="'Photos'" v-bind:id="id"/>

Above is how I load the module. You need to handle the @photo and @removePhoto where you included the module.

Here is the module I wrote:

<template>
    <q-uploader v-bind:value="value" ref="uploader" inverted color="red-8" :float- 
    label="labelText" :multiple='allowMultiple' :url="url" hide-upload-progress send- 
    raw hide-upload-button class="col-3" @add="addFile" @remove:cancel="removeFile"/>
</template>

<script>
import { format } from 'quasar'

export default {
    name: "input-camera",
    inheritAttrs: false,
    data() {
        return {
            url: '',
            listenerIndex: null,
        }
    },
    props: { value: Boolean, allowMultiple: Boolean, labelText: String, id: String },
    methods: {

    addFile(file)
    {

    var resizedFile = null;
    file = file[0];
    var that = this;

    if(file.type.match(/image.*/)) {
        // Load the image
        var metaData = {};
        var reader = new FileReader();
        reader.onload = function (readerEvent) {
            var image = new Image();
            image.onload = function (imageEvent) {

                // Resize the image
                var canvas = document.createElement('canvas'),
                    max_size = 1024,                             // edit it, or get it from another param!
                    width = image.width,
                    height = image.height;
                if (width > height) {
                    if (width > max_size) {
                        height *= max_size / width;
                        width = max_size;
                    }
                } else {
                    if (height > max_size) {
                        width *= max_size / height;
                        height = max_size;
                    }
                }
                canvas.width = width;
                canvas.height = height;
                canvas.getContext('2d').drawImage(image, 0, 0, width, height);
                var dataUrl = canvas.toDataURL('image/jpeg');
                var type = 'image/jpeg';

                //choose one of the above
                resizedFile = dataUrl;

                var nextId = that.$refs.uploader._data.files.length;
                nextId = nextId - 1;

                //add image metadata
                metaData['lastModified'] = that.$refs.uploader._data.files[nextId].lastModified;
                metaData['name'] = that.$refs.uploader._data.files[nextId].name;
                metaData['size'] = that.$refs.uploader._data.files[nextId].size;
                metaData['type'] = type;

                //back to parent
                that.addNextListener();
                that.$emit('photo', resizedFile, that.id, metaData);

            }
            image.src = readerEvent.target.result;
        }
        reader.readAsDataURL(file);
    }

},
removeFile(file)
{
    var that = this;
    var toFind = file.name;
    var found = false;
    var tempL = null;

    for(let l = 0; l < this.$refs.uploader._data.files.length; l++)
    {
        if(this.$refs.uploader._data.files[l].name == toFind)
        {
            found = true;
            tempL = l;
            break;
        }
    }
    if(found)
    {
        if(tempL != null) that.removeNextListener(tempL);
        this.$emit('removePhoto', toFind, this.id);
    }
},
updateUploaderImages: function(id, index, image){

  // ToDo: below would work, but then we need other way to handle the original image
  // this.$refs.uploader._data.files[index]['__img'].src = image;

},
addNextListener(nextListener)
{

    var that = this;
    if(nextListener == null)
    {
      nextListener = this.$refs.uploader._data.files.length-1;
      const childs = this.$refs.uploader.$el.children[1].children[0].children[nextListener].children[0];
      childs.id = 'image'+nextListener;
      var selector = 'div#image'+nextListener;
      this.listenerIndex = nextListener;

      this.setListener(selector, 'click', that.openPopup, that.$refs.uploader.files[nextListener]);
    }else{
      for(let l = 0; l < nextListener.length; l++)
      {
        var listenerIndex = nextListener[l];
        const childs = this.$refs.uploader.$el.children[1].children[0].children[listenerIndex].children[0];
        childs.id = 'image'+listenerIndex;
        var selector = 'div#image'+listenerIndex;
        this.listenerIndex = listenerIndex;

        this.setListener(selector, 'click', that.openPopup, that.$refs.uploader.files[listenerIndex]);
      }
    }
},
removeNextListener(index)
{
    var that = this;
    var nextListener = index;
    var selector = 'div#image'+nextListener;

    this.removeListener(selector, 'click', that.openPopup, that.$refs.uploader.files[nextListener]);

},
openPopup(img)
{
    var that = this;
    img = img['__img'].src;
    this.$emit('popup', img , that.listenerIndex, that.id);
},
setListener(selector, event, callback, props)
{
    var that = this;
    var listenerElements = document.querySelectorAll(selector);
    if(listenerElements != null)
    {
        for(var le=0; le<listenerElements.length; le++)
        {
            listenerElements[le].addEventListener(event, function(evt) {
                if(callback != null) callback(props);
            });
        }
    }
},
removeListener(selector, event, callback, props)
{
    var that = this;
    var listenerElements = document.querySelectorAll(selector);
    if(listenerElements != null)
    {
        for(var le=0; le<listenerElements.length; le++)
        {
            listenerElements[le].removeEventListener(event, function(evt) {
                if(callback != null) callback(props);
            });
        }
    }
},
setImage(photos, id) {

    var that = this;
    var index = id - 1;
    var listenerIndexes = [];

    for(let l = 0; l < photos.length; l++)
    {

        var length = that.$refs.uploader._data.files.length;
        var img = new Image;
        // img.src = photos[l][id];
        img.src = photos[l][l+1];
        var metadata = photos[l].metaData;

        var imgObject = {};
        imgObject.lastModified = metadata.lastModified;
        var DateTime = new Date(metadata.lastModified);
        imgObject.lastModifiedDate = DateTime;
        imgObject.name = metadata.name;
        imgObject.size = metadata.size;
        imgObject.type = metadata.type;
        imgObject.webkitRelativePath = "";
        imgObject.__doneUploading = false;
        imgObject.__failed = false;
        imgObject.__img = img;
        imgObject.__progress = 0;
        imgObject.__size = (metadata.size / 1024)+" kB";
        imgObject.__timestamp = metadata.lastModified;
        imgObject.__uploaded = false;

        this.$refs.uploader._data.files[length] = imgObject;
        this.$refs.uploader.totalSize = this.$refs.uploader.totalSize + 
        imgObject.size;
        this.$refs.uploader.queue.push(imgObject);
        this.$refs.uploader.expanded = true;

        listenerIndexes.push(length);

    }

      setTimeout(function(){
        that.addNextListener(listenerIndexes);
      },50);

  },
},
computed: {
inputListeners: function () {
  var vm = this
  // `Object.assign` merges objects together to form a new object
  return Object.assign({},
    // We add all the listeners from the parent
    this.$listeners,
    // Then we can add custom listeners or override the
    // behavior of some listeners.
    {
      // This ensures that the component works with v-model
      input: function (event) {
        vm.$emit('input', event);
        //if(!isNaN(event)) vm.$emit('input', event.toString().replace('.',''))
        //else return event.slice(0, -1);
          }
        }
      )
    }
  },
}

</script>

It also includes downscaling and sets Clicklisteners for the images, so you can open it inside of a popup. And you are able to insert an image by datauri back into the uploader, if you get it back from the server.

Then I just add the imageData to a json-object and send it to server, where it gets handled.

Hopefully it helps you out a bit.

PS: I disabled the upload-button, so on each add the photoData gets returned and i pushed it into an array and started the sending of the data on another button in UI.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.