0

I'd like to change the URLs from data:image base64 to blob. This is the original code that produces the base64 urls:

<script>

    $(window).load(function(){

    function readURL() {
        var $input = $(this);
        var $newinput =  $(this).parent().parent().parent().find('.portimg ');
        if (this.files && this.files[0]) {
            var reader = new FileReader();
            reader.onload = function (e) {
                reset($newinput.next('.delbtn'), true);
                $newinput.attr('src', e.target.result).show();
                $newinput.after('<div class="delbtn delete_upload"  title="Remove"><span class="bbb-icon bbb-i-remove2"></span></div>');


$("form").on('click', '.delbtn', function (e) {
    reset($(this));
    $("form").find('#rright-<?php echo $i;?>').hide();
  });
            }
            reader.readAsDataURL(this.files[0]);
        }
    }
    $(".file").change(readURL);


    function reset(elm, prserveFileName) {
        if (elm && elm.length > 0) {
            var $input = elm;
            $input.prev('.portimg').attr('src', '').hide();

            if (!prserveFileName) {
                $($input).parent().parent().parent().find('input.file ').val("");
                //input.fileUpload and input#uploadre both need to empty values for particular div
            }
            elm.remove();
        }
    }

    });

  </script>

What I want is to call Object.createObjectURL(this.files[0]) to get the object URL, and use that as the src of your img; (just don't even bother with the FileReader).

Alex333
  • 217
  • 1
  • 5
  • 1
    You already have the Blob though in `this.files[0]` why go through the expense of translating it back from base 64? – Heretic Monkey Jan 03 '20 at 14:46
  • @HereticMonkey But how do I get that instead of base64? – Alex333 Jan 03 '20 at 16:31
  • Where are you trying to get the Blob? I mean all you really have to do is cache `this.files[0]` in a variable somewhere where you can use it. – Heretic Monkey Jan 03 '20 at 17:42
  • @HereticMonkey I should've explained myself better. Right now the link looks like this: `src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAY0AAAGNCAIAAABixbqGAAAABGdBTUEAALGPC/xhBQAAAAlw......` and it's a mile long. I want it to look like this `src="blob:https://mysite.c o m/98cd2703-9e3f-4115-8e20-abdc16fef4ad"` – Alex333 Jan 03 '20 at 20:26
  • Please [edit] your question to make that clear. What you really want then is to just call `Object.`[`createObjectURL`](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL)`(this.files[0])` to get the object URL, and use that as the `src` of your `img`; just don't even bother with the `FileReader`. – Heretic Monkey Jan 03 '20 at 20:34
  • @HereticMonkey ok, I edited it. Would you be able to help me? I don't know how many people are going to see this post. It didn't get any questions or solutions this far. – Alex333 Jan 03 '20 at 20:44

2 Answers2

1

Something like this?

function readURL() {
  var file = this.files[0]
  var reader = new FileReader();
  var base64string = getBase64(file);
  reader.onload = function () {
    reset($newinput.next('.delbtn'), true);
    $newinput.attr('src', e.target.result).show();
    $newinput.after('<div class="delbtn delete_upload"  title="Remove"><span class="bbb-icon bbb-i-remove2"></span></div>');

    var blob = dataURItoBlob(base64string);
  };
  reader.onerror = function (error) {
    console.log('Error: ', error);
  };
}
ssten
  • 1,848
  • 1
  • 16
  • 28
  • @ ssten I updated my original post. This is what I actually need. I wasn't sure how to articulate it when I first posted my question. – Alex333 Jan 03 '20 at 20:46
-1

I'm not sure if this will work and due to the vagaries of Stack Snippets, can't demonstrate its viability here on Stack Overflow, but theoretically, you should be able to use URL.createObjectURL to create the appropriate URL for your image, without going through the whole base 64 rigmarole.

var $newinput =  $(this).parent().parent().parent().find('.portimg ');
if (this.files && this.files[0]) {
    $newinput.attr('src', URL.createObjectURL(this.files[0]));
    // if the above doesn't work, you could try to create a new Blob
    var fileBlob = new Blob(this.files[0], { type: "image/png" }) 
    // Substitute "image/png" with whatever image type it is
    $newinput.attr('src', URL.createObjectURL(fileBlob));

That should render the appropriate URL for the image's source.

Note that it is best practice to revoke the object URL when you are done with it. I'm not sure that's necessary in this case, since presumably you want to show the image until the page is closed. However, if the user can upload a new image, do something like:

if ($newinput.attr('src').indexOf('blob') > -1) {
    URL.revokeObjectURL($newinput.attr('src'));
}

Add that before setting the new source and you shouldn't need to worry about memory leaks (from this use of createObjectURL anyway...).

For more information on Blob URLs, see this answer by a now-anonymous user to What is a blob URL and why it is used?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • Sorry, it's not working... The image doesn't show and there's nothing there when I inspect the elements. – Alex333 Jan 03 '20 at 21:52
  • @Alex333 Sorry, this is what happens when I multitask. The `createObjectURL` is on the `URL` object, not on `Object`. – Heretic Monkey Jan 03 '20 at 21:56
  • Hey, it's half way there! When I inspect the elements the new blob link is there, however the image isn't showing. Something in the code is preventing from the image to show... what that might be? This line? `$newinput.attr('src', e.target.result).show();`? – Alex333 Jan 03 '20 at 22:11
  • You might need to specify the type of image... That should be part of the File Blob you get from `this.files[0]`, but maybe it's not there? I'll amend my answer with something to try. – Heretic Monkey Jan 03 '20 at 22:15
  • It's not doing it. I wonder if the problem is in this line `reader.onload = function (e) {` we don't have the reader anymore since this line is gone `var reader = new FileReader();` – Alex333 Jan 03 '20 at 22:32
  • Oh, yeah, sorry, remove all that reader stuff. You don't need the reader at all, so you don't need `reader.onload` or `reader.readAsDataURL` – Heretic Monkey Jan 03 '20 at 22:33
  • Not sure, maybe I am not doing it right but removing it didn't help. How much would your remove? I do need all that other stuff under `reader.onload = function (e) {` what would you change `reader.onload = function (e) {` to? – Alex333 Jan 03 '20 at 22:40
  • I'd remove that line and the corresponding `}`. – Heretic Monkey Jan 03 '20 at 22:44
  • That's fine; that hooks up your file input to the function and you want to keep that going. – Heretic Monkey Jan 03 '20 at 22:45
  • Removing `reader.onload = function (e) {` and the corresponding `}` didn't solve the issue. – Alex333 Jan 03 '20 at 22:48
  • I see the blob link in the inspect elements, I know the image is there it's just not showing. – Alex333 Jan 03 '20 at 22:49
  • Do you think it will help if you have a working example? Here it is: https://jsfiddle.net/vgwz4q9L right now it shows images via `data:image/png;base64`. Thank you! – Alex333 Jan 04 '20 at 21:24
  • `$newInput` does not refer to an `img`. See https://jsfiddle.net/6kwfbzcx/, where I add a new image, set it to the object URL and it displays fine. Reconsider your method of selecting the element. – Heretic Monkey Jan 05 '20 at 01:47