সার্ভারে একটি চিত্র হিসাবে একটি এইচটিএমএল 5 ক্যানভাস কীভাবে সংরক্ষণ করবেন?


260

আমি একটি জেনারেটর আর্ট প্রকল্পে কাজ করছি যেখানে আমি ব্যবহারকারীদের একটি অ্যালগরিদম থেকে ফলাফলগুলি সংরক্ষণ করতে দিতে চাই to সাধারণ ধারণাটি হ'ল:

  • জেনারেটরি অ্যালগরিদম ব্যবহার করে এইচটিএমএল 5 ক্যানভাসে একটি চিত্র তৈরি করুন
  • চিত্রটি সম্পূর্ণ হয়ে গেলে, ব্যবহারকারীদের সার্ভারে ইমেজ ফাইল হিসাবে ক্যানভাস সংরক্ষণ করার অনুমতি দিন
  • ব্যবহারকারীকে হয় হয় চিত্রটি ডাউনলোড করতে বা এ্যালগোরিদম ব্যবহার করে উত্পাদিত টুকরোগুলির গ্যালারীটিতে যুক্ত করতে।

তবে আমি দ্বিতীয় ধাপে আটকে আছি। গুগলের কাছ থেকে কিছু সহায়তার পরে, আমি এই ব্লগ পোস্টটি পেয়েছি , যা দেখতে আমি ঠিক চাইছিলাম বলে মনে হয়েছিল:

যা জাভাস্ক্রিপ্ট কোডে নেতৃত্ব দিয়েছে:

function saveImage() {
  var canvasData = canvas.toDataURL("image/png");
  var ajax = new XMLHttpRequest();

  ajax.open("POST", "testSave.php", false);
  ajax.onreadystatechange = function() {
    console.log(ajax.responseText);
  }
  ajax.setRequestHeader("Content-Type", "application/upload");
  ajax.send("imgData=" + canvasData);
}

এবং সম্পর্কিত পিএইচপি (testSave.php):

<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
  $imageData = $GLOBALS['HTTP_RAW_POST_DATA'];
  $filteredData = substr($imageData, strpos($imageData, ",") + 1);
  $unencodedData = base64_decode($filteredData);
  $fp = fopen('/path/to/file.png', 'wb');

  fwrite($fp, $unencodedData);
  fclose($fp);
}
?>

তবে এটি মোটেও কিছু করবে বলে মনে হয় না।

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

$data = $_POST['imgData'];
$file = "/path/to/file.png";
$uri = substr($data,strpos($data, ",") + 1);

file_put_contents($file, base64_decode($uri));
echo $file;

এটি একটি ফাইল তৈরি করে (ইয়ে) তবে এটি দূষিত এবং এতে কোনও কিছুই রয়েছে বলে মনে হয় না। এটি খালি বলে মনে হয় (ফাইলের আকার 0)।

সত্যিই কি এমন কিছু স্পষ্ট আছে যে আমি ভুল করছি? আমি যেখানে আমার ফাইলটি সংরক্ষণ করছি সেগুলি লিখিতযোগ্য, সুতরাং এটি কোনও সমস্যা নয়, তবে কিছুই ঘটছে বলে মনে হচ্ছে না এবং এটি কীভাবে ডিবাগ করা যায় তা আমি সত্যই নিশ্চিত নই।

সম্পাদন করা

সালভিডর ডালির লিঙ্কটি অনুসরণ করে আমি আজকের অনুরোধটি পরিবর্তিত করেছি:

function saveImage() {
  var canvasData = canvas.toDataURL("image/png");
  var xmlHttpReq = false;

  if (window.XMLHttpRequest) {
    ajax = new XMLHttpRequest();
  }
  else if (window.ActiveXObject) {
    ajax = new ActiveXObject("Microsoft.XMLHTTP");
  }

  ajax.open("POST", "testSave.php", false);
  ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  ajax.onreadystatechange = function() {
    console.log(ajax.responseText);
  }
  ajax.send("imgData=" + canvasData);
}

এবং এখন চিত্র ফাইলটি তৈরি হয়েছে এবং খালি নেই! দেখে মনে হচ্ছে বিষয়বস্তুর ধরণটি x-www-form-urlencodedইমেজ ডেটা প্রেরণের অনুমতি হিসাবে এটি পরিবর্তন করে ।

কনসোলটি বেস 64 এর (বরং বৃহত্তর) স্ট্রিংটি দেয় এবং ডেটাফাইলে 140 ডলার কেবি হয়। যাইহোক, আমি এখনও এটি খুলতে পারি না এবং এটি কোনও চিত্র হিসাবে ফর্ম্যাট করা হয়নি বলে মনে হয়।


আপনার প্রদত্ত ব্যবহারগুলিতে প্রথম ব্লগটি পোস্ট করার ajax.send(canvasData );সময় আপনি এটি পছন্দ করেন ajax.send("imgData="+canvasData);। অতএব $GLOBALS["HTTP_RAW_POST_DATA"]আপনি যা প্রত্যাশা করেন তা হবেনা, আপনার সম্ভবত ব্যবহার করা উচিত $_POST['imgData']
ম্যাটিউস হেমস্ট্রোম


ডায়োডিয়াস: আমি ইতিমধ্যে সেই থ্রেডে প্রস্তাবিত কৌশলটি ব্যবহার করছি; তবে, বাস্তবায়ন সম্পর্কে তারা আর কোনও বিবরণ দিতে ব্যর্থ হয়েছে এবং সেখান থেকেই আমি আটকে যাচ্ছি।
নাথান লাঞ্চমায়ার

আমি যখন ফাইলের তথ্য প্রতিধ্বনিত করি ( $dataদ্বিতীয় পিএইচপি কোডে) আমি ফিরে পাই তা খালি লাইন। কেন হবে? দেখে মনে হচ্ছে সম্ভবত পাঠানো ডেটাটি সঠিক নয়, তবে এটি প্রদর্শিত হচ্ছে উদাহরণগুলি দেখানোর মতোই এটি পাঠাচ্ছি ...
নাথান ল্যাচনমায়ার

পিএইচপি কোডটি সরলকরণেরDataUriUpload পরিবর্তে এর উপাদানটির সাথে পিএইচপি-ফাইলআপলোড ব্যবহার করে আরও শক্তিশালী করা যায়। এটি এখানে নথিভুক্ত করা হয়েছে এবং বৈধতা এবং সুরক্ষা কার্যকর করার জন্য অতিরিক্ত কয়েকটি উপায় নিয়ে আসে।
কাও

উত্তর:


241

আপনার যা প্রয়োজন তা কীভাবে অর্জন করবেন তা এখানে একটি উদাহরণ:

1) কিছু আঁকুন ( ক্যানভাস টিউটোরিয়াল থেকে নেওয়া )

<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
    var canvas = document.getElementById('myCanvas');
    var context = canvas.getContext('2d');

    // begin custom shape
    context.beginPath();
    context.moveTo(170, 80);
    context.bezierCurveTo(130, 100, 130, 150, 230, 150);
    context.bezierCurveTo(250, 180, 320, 180, 340, 150);
    context.bezierCurveTo(420, 150, 420, 120, 390, 100);
    context.bezierCurveTo(430, 40, 370, 30, 340, 50);
    context.bezierCurveTo(320, 5, 250, 20, 250, 50);
    context.bezierCurveTo(200, 5, 150, 20, 170, 80);

    // complete custom shape
    context.closePath();
    context.lineWidth = 5;
    context.fillStyle = '#8ED6FF';
    context.fill();
    context.strokeStyle = 'blue';
    context.stroke();
</script>

2) ক্যানভাস চিত্রটি ইউআরএল ফর্ম্যাটে রূপান্তর করুন (বেস 64)

var dataURL = canvas.toDataURL();

3) Ajax মাধ্যমে এটি আপনার সার্ভারে প্রেরণ করুন

$.ajax({
  type: "POST",
  url: "script.php",
  data: { 
     imgBase64: dataURL
  }
}).done(function(o) {
  console.log('saved'); 
  // If you want the file to be visible in the browser 
  // - please modify the callback in javascript. All you
  // need is to return the url to the file, you just saved 
  // and than put the image in your browser.
});

3) আপনার সার্ভারে বেস 64 একটি চিত্র হিসাবে সংরক্ষণ করুন (এখানে পিএইচপি-তে এটি কীভাবে করা যায় , প্রতিটি ভাষায় একই ধারণা রয়েছে PH পিএইচপি- তে সার্ভার সাইডটি এখানে পাওয়া যাবে ):


1
আমি বোঝাতে চাইছি যে ফাইলটি আছে তবে আমি এটি ডাউনলোড করলে এটি আমার ব্রাউজারে বা কোনও চিত্র দর্শকের মধ্যে খোলে না।
নাথান লাঞ্চমায়ার

You send it to your server as an ajax requestএই পদ্ধতির ব্যবহারকারীর নিশ্চিতকরণ প্রয়োজন? অথবা আমি চুপচাপ ক্যানভাস থেকে সার্ভারে চিত্র পাঠাতে পারি?
MyTitle

আমি ওয়েব কনসোলে একটি ত্রুটি পেয়েছি। [16: 53: 43.227] সুরক্ষা ত্রুটি: অপারেশনটি নিরাপত্তাহীন। @ sharevi.com/stasing/canvas.html:43 এই সংযোগটি নিরাপত্তাহীন। কিছু করার দরকার আছে? /// আপডেট আপডেট আমি মনে করি আমি জানি কেন, আমি ক্রস ডোমেন চিত্রগুলি ব্যবহার করছিলাম
নিকোলোস ভাসোস

1
তবে আলফা 0 হয় যা এটি কোনও পরিপূর্ণ নয়, এটি সম্পূর্ণ স্বচ্ছ। প্রথম তিনটি মান কী তা নয়।
আবেল ডি

68

আমি এটি নিয়ে দুই সপ্তাহ আগে খেলেছি, এটি খুব সাধারণ। একমাত্র সমস্যাটি হ'ল সমস্ত টিউটোরিয়াল স্থানীয়ভাবে চিত্রটি সংরক্ষণ করার বিষয়ে কথা বলে। এটি আমি এটি করেছিলাম:

1) আমি একটি ফর্ম সেট আপ করেছি যাতে আমি একটি পোষ্ট পদ্ধতি ব্যবহার করতে পারি।

2) ব্যবহারকারীর অঙ্কন সম্পন্ন হওয়ার পরে, তিনি "সংরক্ষণ করুন" বোতামটি ক্লিক করতে পারেন।

3) বোতামটি ক্লিক করা হলে আমি চিত্রের ডেটা নিয়ে তা কোনও গোপন ফিল্ডে রাখি। তারপরে আমি ফর্মটি জমা দিই।

document.getElementById('my_hidden').value = canvas.toDataURL('image/png');
document.forms["form1"].submit();

৪) ফর্মটি জমা দেওয়ার পরে আমার এই ছোট পিএইচপি স্ক্রিপ্ট রয়েছে:

<?php 
$upload_dir = somehow_get_upload_dir();  //implement this function yourself
$img = $_POST['my_hidden'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = $upload_dir."image_name.png";
$success = file_put_contents($file, $data);
header('Location: '.$_POST['return_url']);
?>

1
আমি ক্যানভাস.টো.ডাটাআরএল () ব্যবহার করি তা ঠিক কি? আমার জেপিগ, পিএনজি, জিআইএফ এর মতো ডায়নামিক ফাইল এক্সটেনশন রয়েছে। আমি ক্যানভাস.টো.ডাটাউআরএল চেষ্টা করেছি ('চিত্র / জেপিজি') তবে এটি কাজ করছে না। কোনো সমস্যা?
আইভো সান

আমি এজেএক্সের মাধ্যমে ক্যানভাস থেকে চিত্র পাঠানোর চেষ্টা করতে গিয়ে 413 টি (খুব বড় অনুরোধের অনুরোধ) পেয়েছিলাম। তারপরে এই পদ্ধতির সাহায্যে আমি চিত্রগুলি পেতে পারি।
রায়য়ান

1
কোনও কারণেই এটি আমাকে একটি 0 কেবি পিএনজি ফাইল দিচ্ছে?
প্রিন্সস্পেকস

3
Jpg এর জন্য আপনাকে ক্যানভাস.টোডাটা ইউআরএল করতে হবে ('ইমেজ / জেপিগ') - কমপক্ষে এটি আমার পক্ষে ক্রোমে কী করেছে তা জানায়।
ক্রিস

আপনাকে ধন্যবাদ, আমার যা প্রয়োজন ছিল: ডি
ফসআভান্স

21

আমি মনে করি আপনার বেস্ব 64 এর সাথে ইমেজটি ব্লব সহ চিত্রটি ট্রান্সফার করা উচিত, কারণ আপনি যখন বেস 64 ইমেজটি ব্যবহার করেন তখন এটি প্রচুর লগ লাইন নেয় বা প্রচুর লাইন সার্ভারে প্রেরণ করবে। ব্লব সহ, এটি কেবল ফাইল। আপনি এই কোডটি নমুনা ব্যবহার করতে পারেন:

dataURLtoBlob = (dataURL) ->
  # Decode the dataURL
  binary = atob(dataURL.split(',')[1])
  # Create 8-bit unsigned array
  array = []
  i = 0
  while i < binary.length
    array.push binary.charCodeAt(i)
    i++
  # Return our Blob object
  new Blob([ new Uint8Array(array) ], type: 'image/png')

এবং ক্যানভাস কোড এখানে:

canvas = document.getElementById('canvas')
file = dataURLtoBlob(canvas.toDataURL())

এর পরে আপনি ফর্মের সাথে এজাক্স ব্যবহার করতে পারেন:

  fd = new FormData
  # Append our Canvas image file to the form data
  fd.append 'image', file
  $.ajax
    type: 'POST'
    url: '/url-to-save'
    data: fd
    processData: false
    contentType: false

কফিস্ক্রিপ্ট সিনট্যাক্স ব্যবহার করে এই কোড।

আপনি যদি জাভাস্ক্রিপ্ট ব্যবহার করতে চান তবে দয়া করে কোডটি http://js2.coffee এ পেস্ট করুন


12

পিএইচপি তে ক্যানভাস চিত্র পাঠান:

var photo = canvas.toDataURL('image/jpeg');                
$.ajax({
  method: 'POST',
  url: 'photo_upload.php',
  data: {
    photo: photo
  }
});

এখানে পিএইচপি স্ক্রিপ্ট:
photo_upload.php

<?php

    $data = $_POST['photo'];
    list($type, $data) = explode(';', $data);
    list(, $data)      = explode(',', $data);
    $data = base64_decode($data);

    mkdir($_SERVER['DOCUMENT_ROOT'] . "/photos");

    file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/photos/".time().'.png', $data);
    die;
?>

9

আপনি যদি জাভাস্ক্রিপ্ট canvas.toDataURL()ফাংশন থেকে প্রাপ্ত ডেটা সংরক্ষণ করতে চান , আপনাকে ফাঁকাগুলি প্লাসে রূপান্তর করতে হবে। যদি আপনি এটি না করেন তবে ডিকোড করা ডেটাগুলি দূষিত হবে:

<?php
  $encodedData = str_replace(' ','+',$encodedData);
  $decocedData = base64_decode($encodedData);
?>

http://php.net/manual/ro/function.base64-decode.php


7

আমি অনুরূপ কিছু নিয়ে কাজ করেছি। ক্যানভাস বেস 64-এনকোড চিত্রটি রূপান্তর করতে হয়েছিল Uint8Array Blob

function b64ToUint8Array(b64Image) {
   var img = atob(b64Image.split(',')[1]);
   var img_buffer = [];
   var i = 0;
   while (i < img.length) {
      img_buffer.push(img.charCodeAt(i));
      i++;
   }
   return new Uint8Array(img_buffer);
}

var b64Image = canvas.toDataURL('image/jpeg');
var u8Image  = b64ToUint8Array(b64Image);

var formData = new FormData();
formData.append("image", new Blob([ u8Image ], {type: "image/jpg"}));

var xhr = new XMLHttpRequest();
xhr.open("POST", "/api/upload", true);
xhr.send(formData);

4

সালভাদোর ডালির উত্তর ছাড়াও:

সার্ভারের দিকে ভুলে যাবেন না যে ডেটা বেস 64 স্ট্রিং ফর্ম্যাটে আসে । এটি গুরুত্বপূর্ণ কারণ কিছু প্রোগ্রামিং ভাষায় আপনাকে স্পষ্ট করে বলতে হবে যে এই স্ট্রিংটিকে বাইট হিসাবে বিবেচনা করা উচিত সাধারণ ইউনিকোড স্ট্রিং নয় ।

অন্যথায় ডিকোডিং কাজ করবে না: চিত্রটি সংরক্ষণ করা হবে তবে এটি অপঠনযোগ্য ফাইল হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.