ডেটা ইউআরআই ফাইলকে রূপান্তর করুন তারপরে ফর্মডাটাতে যুক্ত করুন


283

আমি মজিলা হ্যাকস সাইটের মতো একটি এইচটিএমএল 5 চিত্র আপলোডারটিকে পুনরায় বাস্তবায়নের চেষ্টা করছি , তবে এটি ওয়েবকিট ব্রাউজারগুলির সাথে কাজ করে। কাজের অংশটি হ'ল canvasঅবজেক্ট থেকে একটি চিত্র ফাইল বের করা এবং আপলোডের জন্য এটি একটি ফর্মডাটা অবজেক্টে যুক্ত করা।

সমস্যাটি হ'ল ইমেজ ফাইলটির একটি প্রতিনিধিত্ব ফিরিয়ে canvasদেওয়ার toDataURLফাংশন থাকা অবস্থায় , ফর্মডাটা অবজেক্টটি কেবল ফাইল এপিআই থেকে ফাইল বা ব্লব অবজেক্ট গ্রহণ করে ।

মোজিলা সমাধানটিতে নিম্নলিখিত ফায়ারফক্স-কেবলমাত্র ফাংশনটি ব্যবহৃত হয়েছিল canvas:

var file = canvas.mozGetAsFile("foo.png");

... যা ওয়েবকিট ব্রাউজারগুলিতে উপলভ্য নয়। আমি সবচেয়ে ভাল সমাধানটি ভাবতে পারি তা হ'ল কোনও ডেটা ইউআরআইকে একটি ফাইল অবজেক্টে রূপান্তর করার জন্য কোনও উপায় অনুসন্ধান করা, যা আমি ভেবেছিলাম ফাইল এপিআইয়ের অংশ হতে পারে, তবে আমার জীবনের পক্ষে এটি করার জন্য আমি কিছু খুঁজে পাচ্ছি না।

এটা কি সম্ভব? তা না হলে কোন বিকল্প?

ধন্যবাদ।


: আপনি সার্ভার একটি ইমেজ DataURI সংরক্ষণ করতে চান তাহলে stackoverflow.com/a/50131281/5466401
Sibin জন Mattappallil

উত্তর:


471

কয়েকটি জিনিস নিয়ে ঘুরে দেখার পরে, আমি নিজেই এটি বের করতে সক্ষম হয়েছি।

প্রথমত, এটি একটি ডেটা ইউআরআইকে একটি ব্লাবে রূপান্তরিত করবে:

function dataURItoBlob(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    return new Blob([ia], {type:mimeString});
}

সেখান থেকে কোনও ফর্মের সাথে ডেটা যুক্ত করা যাতে এটি ফাইল হিসাবে আপলোড করা সহজ:

var dataURL = canvas.toDataURL('image/jpeg', 0.5);
var blob = dataURItoBlob(dataURL);
var fd = new FormData(document.forms[0]);
fd.append("canvasImage", blob);

29
কেন এটি সর্বদা ঘটে ... আপনি এখানে এবং সেখানে অনুসন্ধানের মাধ্যমে কয়েক ঘন্টা ধরে সমস্যার সমাধানের চেষ্টা করেন। তারপরে আপনি একটি প্রশ্ন পোস্ট করুন। এক ঘন্টার মধ্যে আপনি অন্য প্রশ্নের উত্তর পেয়ে যাবেন। এমন নয় যে আমি অভিযোগ করছি ... stackoverflow.com/questions/9388412/...
syaz

@stoive আমি ব্লব contruct সক্ষম কিন্তু আপনি দয়া করে ব্যাখ্যা করতে পারেন কিভাবে আপনি গঠন করা না POSTবা PUTএস 3 কিভাবে?
গৌরব শাহ

1
@ মিমো - এটি অন্তর্নিহিত দিকে নির্দেশ করে ArrayBuffer, যা পরে BlobBuilderউদাহরণটিতে লেখা হয় ।
স্টোইভ

2
@ স্টাইভ সেক্ষেত্রে কেন এটি বিবি অ্যাপেনড নয় (আইআইএ)?
মিমো

4
ধন্যবাদ! এটি আমার সমস্যাটিকে একটি ছোট সংশোধন দিয়ে সমাধান করেছেvar file = new File( [blob], 'canvasImage.jpg', { type: 'image/jpeg' } ); fd.append("canvasImage", file);
প্রসাদ 19sara

141

ব্লববিল্ডার এবং অ্যারেবফারকে এখন অবচয় করা হয়েছে, ব্লব নির্মাতার সাথে আপডেট হওয়া শীর্ষস্থানীয় মন্তব্যের কোডটি এখানে:

function dataURItoBlob(dataURI) {
    var binary = atob(dataURI.split(',')[1]);
    var array = [];
    for(var i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
}

2
কেবল একটি ধারণা: array=[]; array.length=binary.length;... array[i]=bina... ইত্যাদি তাই অ্যারেটি পূর্ব বরাদ্দ করা হয়েছে। এটি প্রতিটি পুনরাবৃত্তির অ্যারে প্রসারিত করে একটি ধাক্কা () সংরক্ষণ করে এবং আমরা এখানে লক্ষ লক্ষ আইটেম (= বাইট) প্রসেস করছি, সুতরাং এটি গুরুত্বপূর্ণ।
ডিডিএস

2
সাফারিতে আমার জন্যও ব্যর্থ। @WilliamT। যদিও এর উত্তর ফায়ারফক্স / সাফারি / ক্রোমের পক্ষে কাজ করে।
অস্পষ্টরবোট

"বাইনারি" একটি সামান্য বিভ্রান্তিকর নাম, কারণ এটি বিটের অ্যারে নয়, বাইটের অ্যারে।
নীলস অ্যাবিল্ডগার্ড

1
"প্রকার: 'চিত্র / জেপেইগ'" - এটি যদি পিএনজি চিত্র হয় বা আপনি যদি চিত্রের প্রসার আগেই জানেন না তবে কী হবে?
জ্যাসপার

প্রথমে ইউিন্ট 8আরে তৈরি করা একটি অ্যারে তৈরির চেয়ে ভাল এবং তারপরে ইউিন্ট 8আরে রূপান্তরিত।
'22

52

এটি আইওএস এবং সাফারিতে কাজ করে।

আপনার স্টোইভের অ্যারেবফার সমাধানটি ব্যবহার করা দরকার তবে আপনি ব্লববিল্ডার ব্যবহার করতে পারবেন না, যেমন ভ্যাভা 720 নির্দেশ করে, সুতরাং এখানে উভয়ের ম্যাশআপ's

function dataURItoBlob(dataURI) {
    var byteString = atob(dataURI.split(',')[1]);
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ab], { type: 'image/jpeg' });
}

11
গ্রেট! তবে আপনি এখনও মাইম স্ট্রিংকে গতিময় রাখতে পারেন, স্টোইভের সমাধানের মতো, আমি মনে করি? [0]; [1] .split ( ''): // মূকাভিনয় উপাদান Var mimeString = dataURI.split ( ',') [0] .split ( '') আলাদা
প্রতি Quested Aronsson

ওয়েবকিট উপসর্গ সহ আইওএস 6 এর ফ্যালব্যাক কী? তুমি কীভাবে এটা পরিচালনা করো?
বিভক্ত করুন

30

ফায়ারফক্সে ক্যানভাস.টোব্লোব () এবং ক্যানভাস.মোজগেটএএসফাইলে () পদ্ধতি রয়েছে।

তবে অন্যান্য ব্রাউজারগুলি তা করে না।

আমরা ক্যানভাস থেকে ডেটাআরল পেতে পারি এবং তারপরে ডেটাআরলকে ব্লব অবজেক্টে রূপান্তর করতে পারি।

এখানে আমার dataURLtoBlob()ফাংশন। এটা খুব সংক্ষিপ্ত।

function dataURLtoBlob(dataurl) {
    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 Blob([u8arr], {type:mime});
}

আপনার ক্যানভাস বা ডেটাআরল পরিচালনা করতে ফর্মডাটা সহ এই ফাংশনটি ব্যবহার করুন।

উদাহরণ স্বরূপ:

var dataurl = canvas.toDataURL('image/jpeg',0.8);
var blob = dataURLtoBlob(dataurl);
var fd = new FormData();
fd.append("myFile", blob, "thumb.jpg");

এছাড়াও, আপনি HTMLCanvasElement.prototype.toBlobনন জেকো ইঞ্জিন ব্রাউজারের জন্য একটি পদ্ধতি তৈরি করতে পারেন ।

if(!HTMLCanvasElement.prototype.toBlob){
    HTMLCanvasElement.prototype.toBlob = function(callback, type, encoderOptions){
        var dataurl = this.toDataURL(type, encoderOptions);
        var bstr = atob(dataurl.split(',')[1]), n = bstr.length, u8arr = new Uint8Array(n);
        while(n--){
            u8arr[n] = bstr.charCodeAt(n);
        }
        var blob = new Blob([u8arr], {type: type});
        callback.call(this, blob);
    };
}

এখন canvas.toBlob()কেবলমাত্র ফায়ারফক্সই নয় সমস্ত আধুনিক ব্রাউজারের জন্য কাজ করে। উদাহরণ স্বরূপ:

canvas.toBlob(
    function(blob){
        var fd = new FormData();
        fd.append("myFile", blob, "thumb.jpg");
        //continue do something...
    },
    'image/jpeg',
    0.8
);

1
এখানে উল্লিখিত ক্যানভাস. টোব্লবটির পলিফিলটি এই সমস্যাটি আইএমএইচও পরিচালনা করার সঠিক উপায়।
Jakob Kruse

2
আমি এই পোস্টে শেষ জিনিসটির উপর জোর দিতে চাই: "এখন ক্যানভাস.টোব্লোব () সমস্ত আধুনিক ব্রাউজারের জন্য কাজ করে।"
এরিক সিমন্তন

25

আমার পছন্দের উপায় হ'ল ক্যানভাস.টো ব্লব ()

তবে যেভাবেই এখানে আনুন base ব্যবহার করে বেস 64 কে একটি বুলে রূপান্তর করার আরও একটি উপায় ^^,

var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="

fetch(url)
.then(res => res.blob())
.then(blob => {
  var fd = new FormData()
  fd.append('image', blob, 'filename')
  
  console.log(blob)

  // Upload
  // fetch('upload', {method: 'POST', body: fd})
})


আনয়ন কী এবং এটি কীভাবে প্রাসঙ্গিক?
রিকার্ডো

আনয়ন একটি আধুনিক এজাক্স পদ্ধতি যা আপনি পরিবর্তে XMLHttpRequestডেটা ইউআরএল ব্যবহার করতে পারেন যেহেতু ডেটা ইউআরএল কেবল একটি ইউআরএল, আপনি এই উত্সটি আনতে এজাক্স ব্যবহার করতে পারেন এবং আপনি নিজেরাই সিদ্ধান্ত নিতে একটি বিকল্প পেয়েছিলেন যে আপনি এটি ব্লব, অ্যারেবুফার বা পাঠ্য হিসাবে চান
অন্তহীন

1
@ ইন্ডলেস 'ফেচ ()' একটি স্থানীয় বেস 64 স্ট্রিং ... সত্যিই চালাক হ্যাক!
দিয়েগো জোরাককি

1
মনে রাখবেন যে রাখুন blob:এবং data:সর্বজনীন সব আনা বাস্তবায়নের দ্বারা সমর্থিত নয়। আমরা এই পদ্ধতির ব্যবহার করি, যেহেতু আমরা জানি যে আমরা কেবল মোবাইল ব্রাউজারগুলি (ওয়েবকিট) নিয়ে কাজ করব, তবে এজ উদাহরণস্বরূপ, কোনও সমর্থন দেয় না এটি: ডেভেলপার.মোজিলা.আর
ইউএস

19

@ স্টাইভ এবং @ ভাভা 20২০ কে ধন্যবাদ, আমি এইভাবে দু'জনকে একত্রিত করে, অবহেলিত ব্লববিল্ডার এবং অ্যারেবফার ব্যবহার করা এড়িয়ে চলেছি

function dataURItoBlob(dataURI) {
    'use strict'
    var byteString, 
        mimestring 

    if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
        byteString = atob(dataURI.split(',')[1])
    } else {
        byteString = decodeURI(dataURI.split(',')[1])
    }

    mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0]

    var content = new Array();
    for (var i = 0; i < byteString.length; i++) {
        content[i] = byteString.charCodeAt(i)
    }

    return new Blob([new Uint8Array(content)], {type: mimestring});
}

12

মোজিলা অনুমান করার জন্য ঝুঁকিপূর্ণ হিসাবে বিবর্তিত মানটি ক্যানভাস.টো ব্লব () ক্যানভাস.জেটএফফিল () নয় বলে মনে হচ্ছে।

আমি এখনও কোনও ব্রাউজার এটি সমর্থন করে দেখছি না :(

এই দুর্দান্ত থ্রেডের জন্য ধন্যবাদ!

এছাড়াও, গ্রহণযোগ্য উত্তরটির চেষ্টা করা যে কেউ ব্লববিল্ডারের সাথে সাবধানতা অবলম্বন করা উচিত কারণ আমি সমর্থন সীমাবদ্ধ করার জন্য খুঁজে পেয়েছি (এবং নামগতির):

    var bb;
    try {
        bb = new BlobBuilder();
    } catch(e) {
        try {
            bb = new WebKitBlobBuilder();
        } catch(e) {
            bb = new MozBlobBuilder();
        }
    }

আপনি কি ব্লববিল্ডারের জন্য অন্য লাইব্রেরির পলিফিল ব্যবহার করছেন?


আমি কোনও পলিফিলবিহীন ক্রোম ব্যবহার করছিলাম এবং নেমস্পেসিংয়ের কথা মনে পড়বে না। আমি অধীর আগ্রহে প্রত্যাশা করি canvas.toBlob()- এটি এর চেয়ে অনেক বেশি উপযুক্ত বলে মনে হয় getAsFile
স্টাইভ

1
BlobBuilderদেখে মনে হচ্ছেBlob
স্যান্ডস্ট্রোম

ব্লববিল্ডার অবনতিহীন এবং এই প্যাটার্নটি ভয়াবহ। আরও ভাল হবে: উইন্ডো.ব্লববিল্ডার = (উইন্ডো.ব্লববিল্ডার || উইন্ডো।ওয়েবকিটব্লববিল্ডার || উইন্ডো। মোজব্লববিল্ডার || উইন্ডো.এমএস ব্লববিল্ডার); নেস্টেড ট্রাই ক্যাচগুলি সত্যিই কুৎসিত এবং যদি কোনও বিল্ডার উপলব্ধ না হয় তবে কি হবে?
ক্রিস হ্যানসন

এ কেমন ভয়ংকর? যদি একটি ব্যতিক্রম নিক্ষেপ করা হয় এবং 1) ব্লববিল্ডার উপস্থিত না থাকে তবে কিছুই হয় না এবং পরবর্তী ব্লকটি কার্যকর করা হয়। 2) যদি এটি বিদ্যমান থাকে তবে একটি ব্যতিক্রম নিক্ষেপ করা হয় তবে তা অবহেলা করা হয় এবং যাইহোক এটি ব্যবহার করা উচিত নয়, তাই এটি পরবর্তী চেষ্টা ব্লকে অবিরত থাকে। মূলত যদি আপনি ব্লব প্রথম সমর্থিত পরীক্ষা হবে, এবং এমনকি toBlob সমর্থনের জন্য এই চেক সামনে
TaylorMac

5
var BlobBuilder = (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder);

চেষ্টা না করেও ব্যবহার করা যায়।

চেক_সিএকে ধন্যবাদ। মহান কাজ.


1
ব্রাউজার যদি অবহেলিত ব্লববিল্ডারকে সমর্থন করে তবে এটি ত্রুটি ফেলবে। ব্রাউজারটি যদি পুরানো পদ্ধতিটিকে সমর্থন করে তবে এটি নতুন পদ্ধতিটিকে সমর্থন করলেও তা ব্যবহার করবে। এটি পছন্দসই নয়, নীচে ক্রিস
বসকোটির

4

স্টাইভের মূল উত্তরটি ব্লবকে সামঞ্জস্য করার জন্য সর্বশেষ লাইনটি পরিবর্তন করে খুব সহজেই ঠিক করা যায়:

function dataURItoBlob (dataURI) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);
    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to an ArrayBuffer
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    // write the ArrayBuffer to a blob, and you're done
    return new Blob([ab],{type: mimeString});
}

3

এখানে স্টোইভের উত্তরের একটি ES6 সংস্করণ রয়েছে :

export class ImageDataConverter {
  constructor(dataURI) {
    this.dataURI = dataURI;
  }

  getByteString() {
    let byteString;
    if (this.dataURI.split(',')[0].indexOf('base64') >= 0) {
      byteString = atob(this.dataURI.split(',')[1]);
    } else {
      byteString = decodeURI(this.dataURI.split(',')[1]);
    }
    return byteString;
  }

  getMimeString() {
    return this.dataURI.split(',')[0].split(':')[1].split(';')[0];
  }

  convertToTypedArray() {
    let byteString = this.getByteString();
    let ia = new Uint8Array(byteString.length);
    for (let i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    }
    return ia;
  }

  dataURItoBlob() {
    let mimeString = this.getMimeString();
    let intArray = this.convertToTypedArray();
    return new Blob([intArray], {type: mimeString});
  }
}

ব্যবহার:

const dataURL = canvas.toDataURL('image/jpeg', 0.5);
const blob = new ImageDataConverter(dataURL).dataURItoBlob();
let fd = new FormData(document.forms[0]);
fd.append("canvasImage", blob);

3

ধন্যবাদ! এই সমাধানের জন্য @ স্টেওভি।

আমি ES6 সংস্করণে সমর্থন যোগ করেছি এবং আনস্কেপ থেকে ডেটা ইউআরআইতে পরিবর্তন করেছি (আনস্কেপ অবমূল্যায়ন করা হয়েছে)।

converterDataURItoBlob(dataURI) {
    let byteString;
    let mimeString;
    let ia;

    if (dataURI.split(',')[0].indexOf('base64') >= 0) {
      byteString = atob(dataURI.split(',')[1]);
    } else {
      byteString = encodeURI(dataURI.split(',')[1]);
    }
    // separate out the mime component
    mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ia], {type:mimeString});
}

1

এটি সহজ করুন: ডি

function dataURItoBlob(dataURI,mime) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs

    var byteString = window.atob(dataURI);

    // separate out the mime component


    // write the bytes of the string to an ArrayBuffer
    //var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    // write the ArrayBuffer to a blob, and you're done
    var blob = new Blob([ia], { type: mime });

    return blob;
}

-2

toDataURL আপনাকে একটি স্ট্রিং দেয় এবং আপনি সেই স্ট্রিংটিকে একটি লুকানো ইনপুটটিতে রাখতে পারেন।


আপনি একটি উদাহরণ দিতে পারেন? আমি একটি বেস 64 স্ট্রিং আপলোড করতে চাই না (যা <input type=hidden value="data:..." />করণীয় তা করবে), আমি ফাইলের ডেটা আপলোড করতে চাই (যেমন কী <input type="file" />করে তা বাদ দিয়ে আপনি এগুলিতে valueসম্পত্তি সেট করার অনুমতি নেই )।
স্টাইভ

এটি একটি উত্তর চেয়ে মন্তব্য করা উচিত। উত্তরটি যথাযথ ব্যাখ্যা সহ বিস্তারিতভাবে বর্ণনা করুন। @ গেট চেন
লাকী

-5

রবীন্দ্র পায়েলের মতো আমারও ঠিক একই সমস্যা ছিল এবং আমি উত্তরটি পেয়েছি। এটা চেষ্টা কর:

var dataURL = canvas.toDataURL("image/jpeg");

var name = "image.jpg";
var parseFile = new Parse.File(name, {base64: dataURL.substring(23)});

2
আপনি কি পার্স.কম ব্যবহার করার পরামর্শ দিচ্ছেন? আপনার উল্লেখ করা উচিত যে আপনার উত্তর নির্ভরতা প্রয়োজন!
পিয়েরে মাউই

2
ডাব্লুটিএফ? কেন কেউ পার্স সার্ভারে বেস64 ইমেজ কোড আপলোড করবে এবং তারপরে ডাউনলোড করবে? আমরা যখন সরাসরি আমাদের সার্ভারগুলিতে বেস64 আপলোড করতে পারি এবং মূল বিষয় হ'ল বেস 64 স্ট্রিং বা চিত্র ফাইল আপলোড করতে একই ডেটা লাগে। এবং আপনি যদি চিত্রটি ডাউনলোড করতে কেবল ব্যবহারকারীকে মঞ্জুরি দিতে চান তবে আপনি এটি ব্যবহার করতে পারেনwindow.open(canvas.toDataURL("image/jpeg"))
রবীন্দ্র পায়েল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.