1

我有一个表单,允许用户上传图像,裁剪该图像(使用 vue-cropperjs 包装器组件)然后上传裁剪的图像(不是原始图像)。

我无法为文件提供正确的格式以便上传。该文件已被转换(编码)为 base64 图像字符串以在页面上显示。我现在需要将其转换(解码)回文件格式以上传(作为默认的图像上传表单输入)。

可以在以下位置找到视图组件:https ://www.npmjs.com/package/vue-cropperjs

以下代码基于此包示例中的代码,我刚刚为此示例添加了上传方法:

<template>
  <div id="app">
    <h2 style="margin: 0;">Vue CropperJS</h2>
    <form @submit.prevent>
      <input v-model="imageName" type="text" />
      <hr />
      <input
        type="file"
        name="image"
        accept="image/*"
        style="font-size: 1.2em; padding: 10px 0;"
        @change="setImage"
      />

      <br />

      <div style="width: 400px; height:300px; border: 1px solid gray; display: inline-block;">
        <vue-cropper
          ref="cropper"
          :guides="true"
          :view-mode="2"
          drag-mode="crop"
          :auto-crop-area="0.5"
          :min-container-width="250"
          :min-container-height="180"
          :background="true"
          :src="imgSrc"
          alt="Source Image"
          :img-style="{ 'width': '400px', 'height': '300px' }"
        ></vue-cropper>
      </div>

      <img
        :src="cropImg"
        style="width: 200px; height: 150px; border: 1px solid gray"
        alt="Cropped Image"
      />
      <br />
      <br />

      <div>Debug Output: {{ cropImg }}</div>

      <br />
      <br />

      <button @click="cropImage" v-if="imgSrc != ''" style="margin-right: 40px;">Crop</button>

      <br />
      <br />

      <button @click="submitForm" v-if="imgSrc != ''">Submit Form</button>
    </form>
  </div>
</template>


<script>
import VueCropper from "vue-cropperjs";
import "cropperjs/dist/cropper.css";

export default {
  components: {
    VueCropper
  },

  data() {
    return {
      imageName: "",
      imgSrc: "",
      cropImg: "",
    };
  },

  methods: {
    setImage(e) {
      const file = e.target.files[0];

      if (!file.type.includes("image/")) {
        alert("Please select an image file");
        return;
      }

      if (typeof FileReader === "function") {
        const reader = new FileReader();

        reader.onload = event => {
          this.imgSrc = event.target.result;
          // rebuild cropperjs with the updated source
          this.$refs.cropper.replace(event.target.result);
        };

        reader.readAsDataURL(file);
      } else {
        alert("Sorry, FileReader API not supported");
      }
    },

    cropImage() {
      // get image data for post processing, e.g. upload or setting image src
      this.cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL();
    },

    submitForm() {
      console.log("imageName: " + this.imageName);
      console.log("cropImg: " + this.cropImg); //Output: data:image/png;base64,iVBORw0KGgoAAA (please note: i've truncated the value for this example)
      //example of an file upload to firebase storage (this could apply for different solutions)
      //I need to convert the base64 date back into a file in order to upload.
      let e = this.cropImg;


      if(e != null) {
        const file = e;
        console.log("upload file: " + file.name);
        fb.storage
          .ref("images/" + file.name)
          .put(file)
          .then(response => {
            //etc
          }
      }
    }
  }
};
</script>

我已经对 blob、解码等进行了一些研究——但一直无法找到可靠的解决方案。

4

1 回答 1

1

好的,我自己能够解决这个问题 - 如果有人感兴趣,我将 base64 url​​ 发送到这个方法:

dataURLtoFile(dataurl, filename) {
  var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
  bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  while(n--){
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, {type:mime});
}

有关更多信息,请参见此处

于 2019-08-12T10:20:42.580 回答