basecamp / trix

A rich text editor for everyday writing
https://trix-editor.org/
MIT License
19.09k stars 1.12k forks source link

Blob URL instead of Image URL When Dragging and Dropping An Image #347

Closed JimCook57 closed 7 years ago

JimCook57 commented 7 years ago

Following the great instructions you provided on how to process dropped images and loading them onto a server, I got it working... sort of.

The image uploads and looks great in trix, but when I get the content, it looks like this with the img tag pointing to a blob:

<div><br></div><div><figure class="attachment attachment-preview jpg" data-trix-attachment="{&quot;contentType&quot;:&quot;image/jpeg&quot;,&quot;filename&quot;:&quot;MK4A7952-RT-ME-Edit.jpg&quot;,&quot;filesize&quot;:393670,&quot;height&quot;:960,&quot;href&quot;:&quot;&quot;,&quot;url&quot;:&quot;http://data.mp-app.com/cook/jimtest/MK4A7952-RT-ME-Edit_27-640x960.jpg&quot;,&quot;width&quot;:640}" data-trix-content-type="image/jpeg"><img src="blob:http://localhost/bf0371dd-5376-478b-a31c-f2c5fb300ca2" width="640" height="960"><figcaption class="caption">MK4A7952-RT-ME-Edit.jpg <span class="size">384.44 KB</span></figcaption></figure></div>

When I load that back into trix using loadHTML and then immediately get the content, it has been transformed into what I would expect:

<div><br></div><div><figure class="attachment attachment-preview jpg" data-trix-attachment="{&quot;contentType&quot;:&quot;image/jpeg&quot;,&quot;filename&quot;:&quot;MK4A7952-RT-ME-Edit.jpg&quot;,&quot;filesize&quot;:393670,&quot;height&quot;:960,&quot;href&quot;:&quot;&quot;,&quot;url&quot;:&quot;http://data.mp-app.com/cook/jimtest/MK4A7952-RT-ME-Edit_27-640x960.jpg&quot;,&quot;width&quot;:640}" data-trix-content-type="image/jpeg"><img src="http://data.mp-app.com/cook/jimtest/MK4A7952-RT-ME-Edit_27-640x960.jpg" width="640" height="960"><figcaption class="caption">MK4A7952-RT-ME-Edit.jpg <span class="size">384.44 KB</span></figcaption></figure></div>

Am I missing a step when uploading images the causes the blob to revolve once the trix-add-attachment has completed?

javan commented 7 years ago

Thanks for the report! This issue was recently introduced in https://github.com/basecamp/trix/pull/341 and would only happen when an attachment is the only content in an editor. You should see the correct URL if you make another change (like typing a character).

JimCook57 commented 7 years ago

Thank you! I am really digging trix. GREAT editor.

alejorivera commented 7 years ago

Hello! I am still seeing this issue on Trix 10.1, but only when uploading from Android devices.

Any ideas?

johndodev commented 7 years ago

Same, still happening for me on trix 0.10.1 :/, on desktop (chrome).

javan commented 7 years ago

Can you share your JavaScript for uploading / updating attachments?

johndodev commented 7 years ago

It's a little more complex than expected.. It's working, sometimes. It worked when I developped that a few month ago. Now, boss tell me it isn't so I checked and he was right, then I found this post.

Actually, when I retry with the same picture, it's working. Seems it's working when the picture is fast to upload (I have php stuff who prevent upload same picture multiple times, it give you the stored url if it already exist (md5_file)). Anyway, I recorded the behavior : http://recordit.co/JGkAyQJJDF

The JS is a little messy, not very clean and mixed with some other feature I added (localstorage, ...). Do you really want it ?

javan commented 7 years ago

Are you updating the attachment's URL after the XHR upload completes? Something like attachment.setAttributes({ url: "..." }).

johndodev commented 7 years ago

Yes, there is a part of the JS :

this.$this.on('trix-attachment-add', function (e) {
        var attachment = e.originalEvent.attachment;

        if (!attachment.file) {
            e.preventDefault();
            return false;
        }

        self.nbUploadingFiles++;

        self.$submitBtn.attr('disabled', true);
        self.$spinner.show();

        var form_data = new FormData();
        form_data.append('attachment[uploadedFile]', attachment.file);

        $.post({
            url: app.trix_upload_url,
            enctype: 'multipart/form-data',
            data: form_data,
            processData: false,
            cache: false,
            contentType: false,
            xhr: function () {
                var xhr = $.ajaxSettings.xhr();
                xhr.upload.onprogress = function (e) {
                    attachment.setUploadProgress(e.loaded / e.total * 100);
                };
                return xhr;
            },
            xhrFields: {
                withCredentials: true
            }
        }).then(function (response) {
            console.log(response);
            attachment.setAttributes({
                url: response.url,
                href: response.url,
                // pour le récupérer dans le champ attachments et dans le php
                id: response.id
            });
            self.nbUploadingFiles--;

            if (!self.nbUploadingFiles) {
                self.$submitBtn.removeAttr('disabled');
                self.$spinner.hide();
            }
        }).fail(function (e) {
            alert('Error, please try later');
            console.log(e);
        });
    }).on('trix-attachment-remove', function (e) {
        self.editor.composition.removeAttachment(e.originalEvent.attachment)
    });
javan commented 7 years ago

It's not clear to me where blob:http:// URLs are appearing in the video you recorded.

johndodev commented 7 years ago

Yeah sorry, actually it show up when I check the URL of the "img src". On the video, when the picture doesn't appear, it's because it is blobed. The "break picture img" isn't on the video because I also use a php "html purifier" tool, but there is a screen when I disabled it. The purifier is not used at all when I upload and store the content of the editor on databse of course.

picture

javan commented 7 years ago

I see. I'll try to reproduce by faking an immediate XHR response.

Does adding a brief delay fix it for you?

.then(function (response) {
  requestAnimationFrame(function() {
    attachment.setAttributes({
      url: response.url,
      href: response.url,
      // pour le récupérer dans le champ attachments et dans le php
      id: response.id
    })
  })
  ...
})
johndodev commented 7 years ago

Unfortunatly no. I'm not even sure it is related to time..

javan commented 7 years ago

Seems it's working when the picture is fast to upload

So you're only getting blob URLs when the upload is slow?

johndodev commented 7 years ago

For now, with tests I make, it happend when there is something to upload. The upload may be fast I guess. I'm trying to remove maximum of JS on my code to avoid interference but still.

johndodev commented 7 years ago

Bad response, I mean, I tried to add 2 secondes sleep on the controller which upload on the cloud, the bug still not showing up when I already uploaded the picture. When a picture pass, with no bug, there is no way to retrieve the bug. Maybe some chrome cache or something ?

johndodev commented 7 years ago

This issue was recently introduced in #341 and would only happen when an attachment is the only content in an editor.

I may be relevant to say I can reproduce the bug event when I type another character in the editor.

But sometimes, it's working even at the first upload of a new picture.

It is a freaking behavior, it's exactly why I don't really like JS (if the bug is related to JS.. I'm even not sure, I'm not sure of anything anymore, I'm lost. where am I ? Who am I ? Hoo, I'm collapsiiiiing).

Sorry, moreover I may be the cause of the bug because of something in my code, but indirectly. I can give you access to the website if you want to experience it yourself.. Also, It's not urgent.

alejorivera commented 7 years ago

Hi! I'm still having this issue as well. What I did to solve it, although in a hack-ish way, was to insert a line break after Trix finishes uploading a file. It seems like after any text change in Trix, it changes the blobs to the correct URLs.

$(document).on("trixUploadEnd", function() {
    editor = $("trix-editor").get(0).editor;
    editor.insertLineBreak();
});

I'll try to reproduce the issue later today and circle back.

javan commented 7 years ago

Just to be clear, are you seeing blob URLs in the serialized HTML (the hidden input element) or in the editor itself?

johndodev commented 7 years ago

Wow, I was looking for the answer with the console, then I saw blob url in the img src in the editor, and I literally see it changed a few seconds after without any move from me. The upload was done. I can try to capture video if you want. It make sense, it is a matter of timing. I think if I wait long enough, I don't have blob anymore.

So, it was in the editor. I dont see any content in the hidden input actually.. I may looking in the wrong one but I didn't find another one.

javan commented 7 years ago

You can get the hidden input's value in the console with:

element = document.querySelector("trix-editor")
element.inputElement.value
// or
element.value
johndodev commented 7 years ago

I just un-hidden the input, there is the behavior. See the blob url changed after a few seconds on his own. http://recordit.co/Q4ShJPT718

kylefox commented 6 years ago

I also encountered this issue, but after some troubleshooting determined it's because the content was being pasted from another tool (Evernote). It's unrelated to Trix, specifically, but thought I'd mention it here because it took me a while to determine the root cause. Maybe it'll save someone else time in the future 🤞

VictorVocter commented 6 years ago

The issue wasn't resolved. Still happens. I DO have another content on the document. Still doesn't work as it's should.

leonardobork commented 5 years ago

Could someone write a decent fix for this?

klaujesi commented 5 years ago

I've been dealing with this same error. I've solved parsing response from server. Which are string, not javascript object.-

image

attrachment.js

    xhr.addEventListener("load", function(event) {
      console.log(xhr)
      if (xhr.status == 200) {
        let path = JSON.parse(xhr.response).path
        var attributes = {
          url: path,
          href: path
        }
        successCallback(attributes)
      }

Check what are you reciving from your server Hope this help.

Attach go my working setup-- trix.zip

kvlsrg commented 4 years ago

Seems issue still exist 😭 Any progress?

ArtemSyzonenko commented 4 years ago

I confirm, issue is still there, pasted image is not shown.

shivendrahandysolver commented 3 years ago

In my case I was listening for trix-change event to get the generated html from the editor. The trix-change event does not fire after the attachment upload so blob URL was saving inside the img src. So to resolve the issue I manually saved the generated HTML after attachment upload.