使用阿波罗上传(GraphQL)的类星体(Vue)上传器

时间:2018-09-10 15:39:45

标签: vue.js graphql apollo quasar

我正在尝试通过阿波罗上传使用Quasar的Uploader上传图像。

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

这是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);
},

在服务器端,我得到了:

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 };
  },
},

到目前为止,对于《守则》。 如果我输入一个新图像,然后按上载按钮,则uploadFactory在file .__ img中包含img-src。如果将数据发送到服务器,则__img-Object完全为空:{}。我试图发送文件,只是文件。__img,试图复制值,但是每次都为空。

有人做到了吗?还是有可能?

仅供参考:如果您尚未听说过类星体或阿波罗,请联系以下链接: Quasar UploaderApollo Upload

1 个答案:

答案 0 :(得分:0)

我做了一个解决方法,但是它可以满足我的需求。

客户:

<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"/>

以上是我加载模块的方式。您需要在包含模块的地方处理@photo和@removePhoto。

这是我写的模块:

<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>

它还包括缩小比例并为图像设置Clicklistener,因此您可以在弹出窗口中打开它。如果您从服务器取回图像,则可以将datauri的图像重新插入上传器中。

然后我只需将imageData添加到json-object并将其发送到服务器,并在该服务器上进行处理。

希望它能对您有所帮助。

PS:我禁用了上载按钮,因此每次添加时都会返回photoData并将其推入数组中,并开始在UI中的另一个按钮上发送数据。