最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to convert a image src from a blob string to data URI - Stack Overflow

programmeradmin2浏览0评论

I have a page where the user can paste an image into a content editable div. When I get the image the src returns a string. When I look in debug tools this is what I see:

<img src="blob:"/>

How do I convert that to a base 64 string?

Here is the test script, /.

// We start by checking if the browser supports the 
// Clipboard object. If not, we need to create a 
// contenteditable element that catches all pasted data 
if (!window.Clipboard) {
   var pasteCatcher = document.createElement("div");
    
   // Firefox allows images to be pasted into contenteditable elements
   pasteCatcher.setAttribute("contenteditable", "");
    
   // We can hide the element and append it to the body,
   pasteCatcher.style.opacity = 0.5;
   document.body.appendChild(pasteCatcher);
 
   // as long as we make sure it is always in focus
   pasteCatcher.focus();
   document.addEventListener("click", function() { pasteCatcher.focus(); });
} 
// Add the paste event listener
window.addEventListener("paste", pasteHandler);
 
/* Handle paste events */
function pasteHandler(e) {
   // We need to check if event.clipboardData is supported (Chrome)
   if (e.clipboardData) {
      // Get the items from the clipboard
      var items = e.clipboardData.items || e.clipboardData.files;
      var itemcount = items ? items.length : 0;
      pasteArea.value = "items found:"+itemcount;
      if (itemcount) {
         // Loop through all items, looking for any kind of image
         for (var i = 0; i < items.length; i++) {
            if (items[i].type.indexOf("image") !== -1) {
               // We need to represent the image as a file,
               var blob = items[i].getAsFile();
               // and use a URL or webkitURL (whichever is available to the browser)
               // to create a temporary URL to the object
               var URLObj = window.URL || window.webkitURL;
               var source = URLObj.createObjectURL(blob);
                
               // The URL can then be used as the source of an image
               createImage(source);
            }
         }
      } else {
   
       			console.log("no items found. checking input");

          // This is a cheap trick to make sure we read the data
          // AFTER it has been inserted.
          setTimeout(checkInput, 1);
       }
   // If we can't handle clipboard data directly (Firefox), 
   // we need to read what was pasted from the contenteditable element
   } else {
   
   console.log("checking input");
    
      // This is a cheap trick to make sure we read the data
      // AFTER it has been inserted.
      setTimeout(checkInput, 1);
   }
}
 
/* Parse the input in the paste catcher element */
function checkInput() {
   console.log("check input");
    
   // Store the pasted content in a variable
   var child = pasteCatcher.childNodes[0];
 
   // Clear the inner html to make sure we're always
   // getting the latest inserted content
   //pasteCatcher.innerHTML = "";
   //console.log( "clearing catcher");
   console.log(child);
    
   if (child) {
      // If the user pastes an image, the src attribute
      // will represent the image as a base64 encoded string.
      if (child.tagName === "IMG") {
         createImage(child.src);
         reader = new FileReader();
         reader.readAsDataURL(child.src);
         reader.loadend = function(e) {
         		console.log(e.target.result);
         }
      }
   }
}
 
/* Creates a new image from a given source */
function createImage(source) {
   var pastedImage = new Image();
   pastedImage.onload = function(e) {
      //pasteArea.text = pastedImage.src;
      console.log(1);
      console.log(e);
      loadImage.src = e.target.src;
      console.log(loadImage.src);
      
   }
   pastedImage.src = source;
}
<textarea id="pasteArea" placeholder="Paste Image Here"></textarea>
<img id="loadImage" />

I have a page where the user can paste an image into a content editable div. When I get the image the src returns a string. When I look in debug tools this is what I see:

<img src="blob:http://www.example./3955202440-AeFf-4a9e-b82c-cae3822d96d4"/>

How do I convert that to a base 64 string?

Here is the test script, http://jsfiddle/bt7BU/824/.

// We start by checking if the browser supports the 
// Clipboard object. If not, we need to create a 
// contenteditable element that catches all pasted data 
if (!window.Clipboard) {
   var pasteCatcher = document.createElement("div");
    
   // Firefox allows images to be pasted into contenteditable elements
   pasteCatcher.setAttribute("contenteditable", "");
    
   // We can hide the element and append it to the body,
   pasteCatcher.style.opacity = 0.5;
   document.body.appendChild(pasteCatcher);
 
   // as long as we make sure it is always in focus
   pasteCatcher.focus();
   document.addEventListener("click", function() { pasteCatcher.focus(); });
} 
// Add the paste event listener
window.addEventListener("paste", pasteHandler);
 
/* Handle paste events */
function pasteHandler(e) {
   // We need to check if event.clipboardData is supported (Chrome)
   if (e.clipboardData) {
      // Get the items from the clipboard
      var items = e.clipboardData.items || e.clipboardData.files;
      var itemcount = items ? items.length : 0;
      pasteArea.value = "items found:"+itemcount;
      if (itemcount) {
         // Loop through all items, looking for any kind of image
         for (var i = 0; i < items.length; i++) {
            if (items[i].type.indexOf("image") !== -1) {
               // We need to represent the image as a file,
               var blob = items[i].getAsFile();
               // and use a URL or webkitURL (whichever is available to the browser)
               // to create a temporary URL to the object
               var URLObj = window.URL || window.webkitURL;
               var source = URLObj.createObjectURL(blob);
                
               // The URL can then be used as the source of an image
               createImage(source);
            }
         }
      } else {
   
       			console.log("no items found. checking input");

          // This is a cheap trick to make sure we read the data
          // AFTER it has been inserted.
          setTimeout(checkInput, 1);
       }
   // If we can't handle clipboard data directly (Firefox), 
   // we need to read what was pasted from the contenteditable element
   } else {
   
   console.log("checking input");
    
      // This is a cheap trick to make sure we read the data
      // AFTER it has been inserted.
      setTimeout(checkInput, 1);
   }
}
 
/* Parse the input in the paste catcher element */
function checkInput() {
   console.log("check input");
    
   // Store the pasted content in a variable
   var child = pasteCatcher.childNodes[0];
 
   // Clear the inner html to make sure we're always
   // getting the latest inserted content
   //pasteCatcher.innerHTML = "";
   //console.log( "clearing catcher");
   console.log(child);
    
   if (child) {
      // If the user pastes an image, the src attribute
      // will represent the image as a base64 encoded string.
      if (child.tagName === "IMG") {
         createImage(child.src);
         reader = new FileReader();
         reader.readAsDataURL(child.src);
         reader.loadend = function(e) {
         		console.log(e.target.result);
         }
      }
   }
}
 
/* Creates a new image from a given source */
function createImage(source) {
   var pastedImage = new Image();
   pastedImage.onload = function(e) {
      //pasteArea.text = pastedImage.src;
      console.log(1);
      console.log(e);
      loadImage.src = e.target.src;
      console.log(loadImage.src);
      
   }
   pastedImage.src = source;
}
<textarea id="pasteArea" placeholder="Paste Image Here"></textarea>
<img id="loadImage" />

I'm testing this in Safari on Mac.

Share Improve this question edited Jan 28, 2018 at 23:04 1.21 gigawatts asked Jan 27, 2018 at 23:58 1.21 gigawatts1.21 gigawatts 17.9k40 gold badges143 silver badges272 bronze badges 2
  • Why exactly do you want a dataURI? If you want to display the image, use directly the blobURI, and if you want to send it to server, use directly the File you have from item.getAsFile(). – Kaiido Commented Jan 28, 2018 at 5:42
  • It is only for client side. I want to allow my application to receive image data from the clipboard but that is not possible on Safari on OSX. So, the user can paste into a div and then I can read the image that was pasted. But the src value is a URI. My application is running in a plugin and only allowed values passed between plugin and browser are strings. – 1.21 gigawatts Commented Jan 28, 2018 at 5:53
Add a ment  | 

2 Answers 2

Reset to default 6

Since the blobURI is generated automatically by the browser, you can use this, which will download the produced image as a new Blob:

const toDataURL = url => fetch(url)
  .then(response => response.blob())
  .then(blob => new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onloadend = () => resolve(reader.result)
    reader.onerror = reject
    reader.readAsDataURL(blob)
  }))

And then on your function createImage(source) { you can call it:

toDataURL(source)
  .then(dataUrl => {
    console.log('RESULT:', dataUrl)
})

This answer is plimentary to @BrunoLM's answer for when you don't have ES6 or you want to read in a different image type.

ES6:

const toDataURL = url => fetch(url)
.then(response => response.blob())
.then(blob => new Promise((resolve, reject) => {
  const reader = new FileReader()
  reader.onloadend = () => resolve(reader.result)
  reader.onerror = reject
  reader.readAsDataURL(blob)
}))

Not ES6 (seems to work the same):

const toDataURL = function(url) { 
    return fetch(url).then(function(response) { 
        return response.blob();
    }).then(function (blob) {
        var type = blob.type;
        var size = blob.size;
        return new Promise(function(resolve, reject) {
            const reader = new FileReader();
            reader.onerror = reject;
            reader.readAsDataURL(blob);
            reader.onloadend = function() {
                return resolve(reader.result);
            }
        }
     )}
)}

Based on my understanding of ES6 (ES6 to not ES6):

var a = url => fetch(url)
var a = function(url) { return fetch(url) } 
var a = function(parameter) { return statement }

var b = (parameter, parameter) => { fetch(param, param) }
var b = function(foo1, foo2) => { return fetch(param, param) }

var c = url = () => resolve(reader.result)
var c = url = function() { return resolve() }

Making a call:

toDataURL(url).then(function(dataUrl) {
    console.log("RESULT:" + dataUrl);
});

Note:
The value returned by the above method is of type "image/tiff" when run in Safari on OSX. If you want to specify another type, such as PNG, there more info on that here.

发布评论

评论列表(0)

  1. 暂无评论