POST canvas 到网络 api

POST canvas to web api

我正在使用 cloudsight api http://cloudsight.readme.io/v1.0/docs 以及我 post 数据所在的字符串。

我还有 canvas 来自网络摄像头的图像。我正在尝试将它发送到 api,但是当我序列化它时 [image] 是空白的。

来自服务器的响应:

{"error":{"image":["can't be blank"]}}

简短片段:

var dataURL = canvas.toDataURL('image/jpeg', 0.5);
var blob = dataURItoBlob(dataURL);
var fd = new FormData(document.forms[0]);
fd.append("file", blob);
/*some code*/
ajax.send("image_request[image]=" + image + "&image_request[locale]=en_US");

// Put event listeners into place
window.addEventListener("DOMContentLoaded", function() {
  // Grab elements, create settings, etc.
  var canvas = document.getElementById("canvas"),
    context = canvas.getContext("2d"),
    video = document.getElementById("video"),
    videoObj = {
      "video": true
    },
    errBack = function(error) {
      console.log("Video capture error: ", error.code);
    };

  // Put video listeners into place
  if (navigator.getUserMedia) { // Standard
    navigator.getUserMedia(videoObj, function(stream) {
      video.src = stream;
      video.play();
    }, errBack);
  } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
    navigator.webkitGetUserMedia(videoObj, function(stream) {
      video.src = window.URL.createObjectURL(stream);
      video.play();
    }, errBack);
  } else if (navigator.mozGetUserMedia) { // WebKit-prefixed
    navigator.mozGetUserMedia(videoObj, function(stream) {
      video.src = window.URL.createObjectURL(stream);
      video.play();
    }, errBack);
  }

  // Trigger photo take
  document.getElementById("snap").addEventListener("click", function() {
    context.drawImage(video, 0, 0, 300, 190);
    saveImage();
  });
}, false);

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



  var ajax = new XMLHttpRequest();
  ajax.open('POST', 'http://api.cloudsightapi.com/image_requests', true);
  ajax.setRequestHeader("Authorization", "CloudSight 0QssZRTUHaRvU1Tt45fnDw");
  ajax.setRequestHeader("Accept", "application/json");
  ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
  ajax.onreadystatechange = function() {
    console.log(ajax.responseText);


  }
  ajax.send("image_request[image]=" + fd + "&image_request[locale]=en_US");
  alert("image_request[image]=" + fd + "&image_request[locale]=en_US");
  /*  ajax.send("image_request[remote_image_url]=http://images.kaneva.com/filestore10/5860810/7181471/iUloveUgs.jpg ");*/
}

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
  });
}
body {
  margin: 0;
}
video {
  width: 100%;
  height: 100%;
}
#snap {
  margin-top: 30px;
  position: absolute;
  right: 50%;
  width: 64px;
  height: 64px;
  transform: translateX(50%);
  text-decoration: none;
  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAED0lEQVR4Xu2b4XnUMAyGpQmACWgngE5AOwFlAugElAkoE9BOQDsB7QSwAWUC2gm4TiCe75Dz5K62E9uyE8jpz/25nK3XsvRZzjEt3Hjh/tMOwC4CFk5gtwUsA0BEnhLRWyLCZw1bEdEVM+PTxMwiQJ3/QUR7JjML/8gtER1ZQbAEcEZEHys7737+AzOfW4xlCeBXg9V3Pt8y88FsAIjISyJC+Le0fWa+Kx3QJAJEBOH4vnQyic+bbAMrAC3D33QbFAOYKPwdhOJtYAHgUmt/YgSbfP2CmU9LfikbgNZ97HuUvykN4wNEljjaACAih5rM8FlLzU0FC4C+Kyx8rq0DICJfiOjdVLNrPO4lM590ABbmvGO9hsAa9t8arcADEV0TEQQMNL3bt9huEFM4RxwT0ZNG8zkCAEzodeUBr4jonJnh9KBpaUV2x8mypt0AwO+KCe+GiE5zJauIICKgMmst0AoApBLiE2aGRig2EUFyRpJOMUQdthoq2qvQgzUAYJ8fjg33sR7ptkD5GpMfPjFzp09EBM95IVgDqOK8g5QA4aC/ACIS7FVYAxgV9qoiX/RyD6rBzzFqbuR2eMPMSO5rE5GgXLcEgF5dVEj1lCZKnc8wacjaTqn5vhRzSL8PoKgi9xr6QbluBQChvxdaQV3xzwlKEyuG875X32t1QEkdkw+iacYKwEbS6Y+ozkNoQeikWLT5GdvXKYNYAQiey0Xkq6q7lHm573aaffthjQI0YorMAgCSl3d1RyasIQc2EtpWdCFKkEyzzQJAsDcnIhatsjtm3g8kQyQ65JZsswCAS4pHWdu4VebdYhYHuZoAilent6zeKJsFAGb2ttWssrRCiFWZorNMcQQsHgARhfan5V2hNwIsSmFxBOhNrS8JQu5CA1iYtxTOIgcQUfAAJCKQsqVy9YGZvR1qC51hEQHBQ5BRIowlwOJ2ngWAFTM/CwgVrBy6MrlRMHTIKm7nWQCA7zG5mnt1Hm2uiIhJjrECEJSroJPQyXGBNNhZMpLZZAUAE492g7RkoTQOtbrRzDyLdZItkp8jbQkAGR+aIHpJqSAQvv37R3dvdz3UQtfn8TaKyd2lJQBANX2Dy9MDgNM5zZWgFrEGgIGCTYwSRZTRVhs1XA0A5pFQ0FYbhFALAAbGvkZ5jHZ4h2aocheS2mTPb49XE4AbCwCg5pJAqON48RLJspq1AOAmjwQJCJDO3lti1Qsok3A6tYucBaklAN8EHYgmzvomAADQ6s+z8P37D90DwBRvec4F3QUAlJ7Y5uJM6jz+njT1sGJyskqdwcTfX59g+6/JIfPiUvJ/zwe4MT52lehRS1vP2ZNl5cpRgf8ZdO8NYKzsV2UrT7TZz+8ANEM904F2ETDThWk2rcVHwB87rBc0IyZ5+AAAAABJRU5ErkJggg==");
}
#snap:active {
  opacity: 0.85;
}
.panel {
  position: fixed;
  bottom: 0px;
  width: 100%;
  margin-top: -4px;
  background-color: #fc0;
  height: 120px;
}
.result {
  display: inline-block;
  width: 100%;
  height: 100%;
}
#overlay {
  height: 80%;
  width: 80%;
  margin: 0 auto;
  background: white;
  color: black;
  padding: 10px;
  position: absolute;
  top: 5%;
  left: 10%;
  z-index: 1000;
  display: none;
  /* CSS 3 */
  border-radius: 10px;
}
#mask {
  /* create are mask */
  position: fixed;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 500;
  width: 100%;
  height: 100%;
  display: none;
}
/* use :target to look for a link to the overlay then we find are mask */

#overlay:target,
#overlay:target + #mask {
  display: block;
  opacity: 1;
}
.close {
  /* to make a nice looking pure CSS3 close button */
  display: block;
  position: absolute;
  top: -20px;
  right: -20px;
  background: red;
  color: white;
  height: 40px;
  width: 40px;
  line-height: 40px;
  font-size: 35px;
  text-decoration: none;
  text-align: center;
  font-weight: bold;
  -webkit-border-radius: 40px;
  -moz-border-radius: 40px;
  -o-border-radius: 40px;
  border-radius: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <meta charset="UTF-8">
  <title>Document</title>

</head>

<body>
  <video id="video" class="video" autoplay></video>

  <div id="qw" class="panel">
    <a href="#overlay" id="snap"></a>
  </div>
  <div id="overlay">
    <a href="#" class="close">&times;</a>
    <canvas class="result" id="canvas"></canvas>
  </div>
  <div id="mask" onclick="document.location='#';"></div>


</body>

</html>

我有一个问题。您不能从客户端发出跨域 post 请求,除非您为请求和响应服务器都设置了 allow-orgin。

您正在尝试将图片作为表单 (fd) 中的字段发送。这不适用于二进制数据 - 至少您将无法使用服务器端的普通工具集处理它。

您必须将二进制数据作为 multipart/formdata 发送,其中文件显示为它自己的 "part"。 Mozilla 有一些 excellent documentation how to do that from JavaScript.