tinymce-vue icon indicating copy to clipboard operation
tinymce-vue copied to clipboard

Problem with Image Upload Credentials property or Image Upload Handler function

Open phyothiha opened this issue 3 years ago • 10 comments

What is the current behavior? Hi, this plugin is magnificent. I'm using the TinyMCE free version for my current project but I have a slight problem with image uploading.

First problem is credentials didn't not send in the request header using along with images_upload_url property as per documentation.

images_upload_credentials

There is also an error with the Image Upload Handler function. I follow the code as per documentation and slightly change according to my project but alert an error with "Cannot read properties of undefined (reading 'then')" after successfully uploading to the server and returning json response as location object.

function example_image_upload_handler(blobInfo, success, failure, progress) {
  console.log("success", success);
  console.log("failure", failure); // this return undefined
  console.log("progress", progress); // this return undefined

  var xhr, formData;
  xhr = new XMLHttpRequest();
  xhr.withCredentials = true;
  xhr.open("POST", process.env.API_BASE_URL + "/api/file-upload");
  var start = document.cookie.search("=");
  var token = document.cookie.slice(start + 1).replace("%3D", "=");
  xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  xhr.setRequestHeader("X-XSRF-Token", token);
  xhr.onload = function () {
    var json;
    if (xhr.status === 403) {
      failure("HTTP Error: " + xhr.status, { remove: true });
      return;
    }
    if (xhr.status < 200 || xhr.status >= 300) {
      failure("HTTP Error: " + xhr.status);
      return;
    }
    json = JSON.parse(xhr.responseText);
    if (!json || typeof json.location != "string") {
      failure("Invalid JSON: " + xhr.responseText);
      return;
    }
    success(json.location);
  };
  xhr.onerror = function () {
    failure(
      "Image upload failed due to a XHR Transport error. Code: " + xhr.status
    );
  };
  formData = new FormData();
  formData.append("file", blobInfo.blob(), blobInfo.filename());
  xhr.send(formData);
}

Which versions of TinyMCE, and which browser / OS are affected by this issue? Did this work in previous versions of TinyMCE or tinymce-vue?

Quasar: 2.6.0 Vue: 3.0.0 TinyMCE: 5.0.0 Browser: Microsoft Edge OS: OSX

phyothiha avatar Oct 31 '22 06:10 phyothiha

Ref: INT-3042

exalate-issue-sync[bot] avatar Oct 31 '22 06:10 exalate-issue-sync[bot]

@phyothiha do you have a small replication or can you post your configuration?

jscasca avatar Oct 31 '22 06:10 jscasca

@jscasca For clarity, I just paste full configuration in Vue Component.

<script setup>
import Editor from "@tinymce/tinymce-vue";

const apiKey = process.env.API_KEY_TINYMCE_EDITOR;

function example_image_upload_handler(blobInfo, success, failure, progress) {
  console.log("success", success);
  console.log("failure", failure);
  console.log("progress", progress);

  var xhr, formData;
  xhr = new XMLHttpRequest();
  xhr.withCredentials = true;
  xhr.open("POST", process.env.API_BASE_URL + "/api/file-upload");
  var start = document.cookie.search("=");
  var token = document.cookie.slice(start + 1).replace("%3D", "=");
  xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  xhr.setRequestHeader("X-XSRF-Token", token);
  xhr.onload = function () {
    var json;
    if (xhr.status === 403) {
      failure("HTTP Error: " + xhr.status, { remove: true });
      return;
    }
    if (xhr.status < 200 || xhr.status >= 300) {
      failure("HTTP Error: " + xhr.status);
      return;
    }
    json = JSON.parse(xhr.responseText);
    if (!json || typeof json.location != "string") {
      failure("Invalid JSON: " + xhr.responseText);
      return;
    }
    success(json.location);
  };
  xhr.onerror = function () {
    failure(
      "Image upload failed due to a XHR Transport error. Code: " + xhr.status
    );
  };
  formData = new FormData();
  formData.append("file", blobInfo.blob(), blobInfo.filename());
  xhr.send(formData);
}

const editorConfig = {
  height: 350,

  branding: false,

  placeholder: "Type something",

  menubar: false,

  plugins: [
    "advlist",
    "anchor",
    "autolink",
    "codesample",
    "fullscreen",
    "image",
    "link",
    "lists",
    "searchreplace",
    "media",
    "table",
    "visualblocks",
    "visualchars",
  ],

  toolbar:
    "undo redo | fontsize forecolor backcolor removeformat | bold italic underline superscript subscript | alignleft aligncenter alignright alignjustify | outdent indent numlist bullist | image media link table codesample | visualblocks visualchars | fullscreen",

  advlist_number_styles:
    "default,lower-alpha,lower-roman,upper-alpha,upper-roman",

  link_default_protocol: "https",

  font_size_formats:
    "12px 13px 14px 16px 18px 24px 30px 36px 48px 60px 72px 96px",

  content_style: "body { font-size: 14px }",

  images_upload_handler: example_image_upload_handler,
};
</script>

<template>
  <editor :api-key="apiKey" :init="editorConfig" />
</template>

phyothiha avatar Oct 31 '22 06:10 phyothiha

@jscasca This code is using images_upload_url and images_upload_credentials property

<script setup>
import Editor from "@tinymce/tinymce-vue";

const apiKey = process.env.API_KEY_TINYMCE_EDITOR;

const imageConfig = {
  images_upload_url: process.env.API_BASE_URL + "/api/file-upload",

  images_upload_credentials: true,
};

const editorConfig = {
  // same as above config
  ...imageConfig,
};
</script>

<template>
  <editor :api-key="apiKey" :init="editorConfig" />
</template>

phyothiha avatar Oct 31 '22 06:10 phyothiha

I cannot replicate usage with the uploader function (adapted to my local environment), everything seems to work properly. Do you have a sample repo where you have this running?

I have not tried using images_uploade_credentials yet

jscasca avatar Oct 31 '22 08:10 jscasca

@jscasca You mean the image uploader function works with your local environment? Ok I'll try with only Vue without using the UI framework. I do not have a sample repo for this. Maybe that might have an issue with the quasar framework.

phyothiha avatar Oct 31 '22 08:10 phyothiha

Yes, even none of the console.logs at the start of the function return undefined for me. They all have functions while using vanilla Vue. I have never tried Quasar so I'm not sure how it interacts with the rest of the components but that might be the issue. If you can create a replication I can look further into it

jscasca avatar Oct 31 '22 08:10 jscasca

@jscasca I set it up on codesandbox with image uploader function contains outputting function result.

phyothiha avatar Oct 31 '22 09:10 phyothiha

Thanks for the replication. That's definitely Quasar breaking stuff. I guess that's the same reason the credentials are not being passed when using the credentials setting.

I would need to look deeper into what Quasar is actually doing to break the function calls.

jscasca avatar Oct 31 '22 10:10 jscasca

@jscasca Doing images_upload_credentials: true didn't pass along credentials such as cookies or authorization headers. I tested it out with vanilla Vue. If I want to pass credentials, I will have to use custom image_upload_handler function and manually set headers.

phyothiha avatar Nov 01 '22 00:11 phyothiha

This issue is stale because it has been open 30 days with no activity. Please comment if you wish to keep this issue open or it will be closed in 7 days.

tiny-stale-bot avatar Jul 09 '24 00:07 tiny-stale-bot

This issue was closed because it has been stalled for 7 days with no activity.

tiny-stale-bot avatar Jul 17 '24 00:07 tiny-stale-bot