使用 Ajax 和 PHP $_FILES 从 Canvas 元素发送图像

2024-01-31

我需要能够将图像和一些表单字段从客户端画布元素发送到 PHP 脚本,最终以 $_POST 和 $_FILES 结束。当我这样发送时:

<script type="text/javascript">
var img = canvas.toDataURL("image/png");
...
ajax.setRequestHeader('Content-Type', "multipart/form-data; boundary=" + boundary_str);
var request_body = boundary + '\n' 
+ 'Content-Disposition: form-data; name="formfield"' + '\n' 
+ '\n' 
+ formfield + '\n' 
+ '\n' 
+ boundary + '\n'
+ 'Content-Disposition: form-data; name="async-upload"; filename="' 
+ "ajax_test64_2.png" + '"' + '\n' 
+ 'Content-Type: image/png' + '\n' 
+ '\n' 
+ img
+ '\n' 
+ boundary;
ajax.send(request_body);
</script>

$_POST 和 $_FILES 都已填充,但 $_FILES 中的图像数据仍然需要像这样解码:

$loc = $_FILES['async-upload']['tmp_name'];
$file = fopen($loc, 'rb');
$contents = fread($file, filesize($loc));
fclose($file);
$filteredData=substr($contents, strpos($contents, ",")+1);
$unencodedData=base64_decode($filteredData);

...为了将其保存为可读的 PNG。这不是一个选项,因为我试图将图像传递给 Wordpress 的 media_handle_upload() 函数,该函数需要 $_FILES 的索引指向可读图像。我也无法相应地解码、保存和更改“tmp_name”,因为它违反了安全检查。

所以,我发现了这个:http://www.webtoolkit.info/javascript-base64.html http://www.webtoolkit.info/javascript-base64.html并尝试在客户端进行解码:

img_split = img.split(",",2)[1];
img_decoded = Base64.decode( img_split );

但由于某种原因,当它到达 PHP 时我仍然没有得到一个可读的文件。 所以问题是:“为什么?”或“我做错了什么?”或“这可能吗?” :-)

非常感谢任何帮助!

谢谢, 凯恩


不幸的是,如果没有一些中间编码,这在 JavaScript 中是不可能的。为了理解原因,我们假设您对数据进行了 Base64 解码并发布,就像您在示例中所描述的那样。有效 PHP 文件的前几行(十六进制)可能如下所示:

0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
0000010: 0000 0080 0000 0080 0806 0000 00c3 3e61  ..............>a

如果您查看上传的 PNG 文件的相同范围的十六进制,它将如下所示:

0000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
0000010: 0000 00c2 8000 0000 c280 0806 0000 00c3  ................

差异是微妙的。比较第二行的第二列和第三列。在有效文件中,这四个字节是0x00 0x80 0x00 0x00。在您上传的文件中,相同的四个字节是0x00 0xc2 0x80 0x00. Why?

JavaScript 字符串是 UTF。这意味着任何 ASCII 二进制值 (0-127) 都用一个字节进行编码。然而,从 128 到 2047 之间的任何数字都可以two字节。那个额外的0xc2上传的文件中是这种多字节编码的产物。如果你想确切地知道为什么会发生这种情况,你可以阅读更多关于维基百科上的 UTF 编码 http://en.wikipedia.org/wiki/UTF-8#Description.

您无法阻止 JavaScript 字符串发生这种情况,因此您无法在不使用 base64 的情况下通过 AJAX 上传此二进制数据。

EDIT:经过进一步挖掘,某些现代浏览器可以实现这一点。如果浏览器支持XMLHttpRequest.prototype.sendAsBinary(Firefox 3 和 4),您可以使用它来发送图像,如下所示:

function postCanvasToURL(url, name, fn, canvas, type) {
  var data = canvas.toDataURL(type);
  data = data.replace('data:' + type + ';base64,', '');

  var xhr = new XMLHttpRequest();
  xhr.open('POST', url, true);
  var boundary = 'ohaiimaboundary';
  xhr.setRequestHeader(
    'Content-Type', 'multipart/form-data; boundary=' + boundary);
  xhr.sendAsBinary([
    '--' + boundary,
    'Content-Disposition: form-data; name="' + name + '"; filename="' + fn + '"',
    'Content-Type: ' + type,
    '',
    atob(data),
    '--' + boundary + '--'
  ].join('\r\n'));
}

对于没有的浏览器sendAsBinary,但确实有Uint8Array(Chrome 和 WebKit),你可以像这样填充它:

if (XMLHttpRequest.prototype.sendAsBinary === undefined) {
  XMLHttpRequest.prototype.sendAsBinary = function(string) {
    var bytes = Array.prototype.map.call(string, function(c) {
      return c.charCodeAt(0) & 0xff;
    });
    this.send(new Uint8Array(bytes).buffer);
  };
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Ajax 和 PHP $_FILES 从 Canvas 元素发送图像 的相关文章

  • 正则表达式上的换行符

    我试图替换两个标签之间的所有内容 但我无法构建正确的表达式 这就是我所做的
  • 尝试使用 php 发送 POST 请求,无论我做什么,我都会收到“HTTP ERROR 500”

    为了发出 HTTP 请求 有人建议我尝试使用 PHP 并给了我一段代码 url https example com dashboard api data array to gt PHONE NUMBER from gt SENDER ID
  • get url 重定向时 File_get_contents() 不起作用

    我正在使用的功能是 function http post url data data url http build query data data len strlen data url date default timezone set
  • CodeIgniter 控制器 - JSON - AJAX

    我正在尝试通过 AJAX 使用 CodeIgniter 发送表单构建 并尝试使用 JSON 获取响应 但是 我只在打开开发人员选项卡时看到响应 我什至不确定这是否实际上是响应 因为它显示了两个 json 数据 它所显示的只是加载旋转器 然后
  • 编辑 HTACCESS 文件以防止直接访问特定文件夹中的特定文件

    我试图阻止直接访问子文件夹中的特定文件 我意识到这个论坛上有很多描述类似问题的主题 但是 我的似乎有点尴尬 由于我已经存在 HTACCESS 文件 这是文件的文件路径 www example com PRINCIPAL PROJECTS m
  • 如何在HTML中的PHP中注释掉HTML和PHP?

    这是我想注释掉的一行代码 h1 class post title a href title a h1 一种流行的注释方法是分别注释 html 和 php 有一个更好的方法吗
  • 如何在多次尝试后延迟登录尝试 (PHP)

    我正在开发一个用 PHP 构建的相当大的网站 该网站可能会有很多用户 我正在寻找一种方法来保护登录屏幕免受自动尝试的影响 我已经在注册表中添加了验证码检查 但还想进一步强化网站 据我所知 StackOverflow 上也有类似的问题 而且我
  • 对 SimpleXML 数据进行排序和分组

    我正在对 XML 文件中的出版物数据进行排序和分组 我目前使用的方法效果很好大部分情况下 尽管我觉得有一种更有效的方法来完成我想要完成的任务 以下是目标节点的示例
  • 重写 URL,将 ID 替换为查询字符串中的标题

    我对 mod rewrite 很陌生 但我做了一些搜索 但找不到这个问题的答案 我有一个网站 它只有一个 PHP 页面 根据查询字符串中传递给它的 ID 提供数十页内容 我想重写 URL 以便此 ID消失并替换为从数据库中提取的页面标题 例
  • 如何在 Zend MVC 中实现 SSL

    我之前已经通过使用特定的安全文件夹 例如服务器上的 https 文件夹与 http 文件夹 实现了安全页面 我已经开始使用 Zend Framework 并希望应用程序的某些部分 例如登录 使用 https 我在谷歌上搜索过 甚至在这里搜索
  • 如何通过ssh检查ubuntu服务器上是否存在php和apache

    如何通过ssh检查Ubuntu服务器上apache是 否安装了php和mysql 另外如果安装的话在哪个目录 如果安装了其他软件包 例如 lighttpd 那么它在哪里 确定程序是否已安装的另一种方法是使用which命令 它将显示您正在搜索
  • 我可以在 PHP 会话变量中安全地存储用户名和密码吗?

    我想在 REST api 之上制作一个轻量级的 web 应用程序 用户只需进行一次身份验证 从那时起 所有针对 web api 的请求都希望通过以某种方式保持用户名和密码有效来完成 我已经做了一个工作原型我在哪里将用户名和密码存储在会话变量
  • 反向引用在 PHP 中不起作用

    最近我一直在研究 更多的是在实践中说实话 正则表达式 我注意到他的力量 我提出的这个要求 link https stackoverflow com questions 30380397 take the text up to a speci
  • phpActiveRecord 日期时间格式不正确

    当尝试使用 phpActiveRecord 在表中创建记录时 出现以下错误 Invalid datetime format 1292 Incorrect datetime value 2013 06 20 11 59 08 PDT for
  • 优雅降级 - 何时考虑

    在为使用 AJAX 的应用程序设计和构建 UI 时 您何时考虑优雅降级 对于禁用 JavaScript 或正在使用屏幕阅读器的用户 最后 网站的 AJAX 版本完全完成后 在每个发展阶段 I don t 还有别的事 这些日子 渐进增强 ht
  • PHP递归遍历对象树[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • ZF3/2 - 如何捕获 EVENT_DISPATCH 侦听器中引发的异常?

    有什么方法可以在 EVENT DISPATCH 监听器中抛出异常吗 class Module public function onBootstrap EventInterface event application event gt get
  • 使用 PHP 将 latin1_swedish_ci 转换为 utf8

    我有一个数据库 里面充满了类似的值 Dhaka 应该是 Dhaka 因为我在创建数据库时没有指定排序规则 现在我想修复它 我无法从最初获取数据的地方再次获取数据 所以我在想是否可以在 php 脚本中获取数据并将其转换为正确的字符 我已将数据
  • 使用 crypt() 加密

    我目前正在做一个非常安全的登录系统 但我是 crypt 函数的新手 需要一些快速帮助 我在注册过程中使用 crypt 加密密码字符串并将其保存到数据库中 但是 我如何在登录过程中解密密钥 或者我应该怎么做 或者是否可以对提交的密码字符串进行
  • 如果产品重量超过1000克,如何以公斤为单位显示

    在 Storefront 主题中 我使用下面的代码将格式化重量从 1000g 更改为 1kg add action woocommerce after shop loop item title show weight 10 function

随机推荐

  • 将所有函数折叠到 R-Studio 脚本中

    基本上我已经在一个 R 脚本中编写了相当多的函数 为了创建更好的概述并且不必滚动太多 我通常按函数定义左侧的箭头 将其折叠 对于 30 多个函数来说 这可能非常烦人 因为当我运行它们时 它们会不断 展开 我所说的折叠的意思可以在这张照片中看
  • code::blocks 是否保留除 C++ 关键字之外的名称?

    我是 code blocks 的新手 而且在 C 方面也没有经验 我知道有很多关键字 我不应该将它们用于变量名称 并且它们通常以不同的颜色显示 就像在 Visualstudio 中一样 现在 当我将一些代码片段从旧的 vs 项目复制到新的
  • Azure - 无法连接到 RDP

    我必须更改管理员密码 因为它已通过 RDP 过期 更改后服务器工作正常 后来我断开了会话 然后再次启动它 现在我们收到以下错误消息 发生身份验证错误 无法联系当地安全机构 远程计算机 cloudapp net 即使两台服务器重新启动后 同样
  • 实际安装模块时 pip install 期间出现 ModuleNotFoundError

    我尝试使用安装 python 包 BentoML pip install bentoml 我收到以下错误 该错误给出了ModuleNotFoundError No module named wrapt 但是 那wrapt模块实际上包含在我的
  • 使用 Powershell 将文件检入 TFS

    作为持续集成构建的一部分 我正在创建一个 SQL 脚本 该 SQL 脚本生成后必须重新签入 TFS 我在 Powershell 中使用 TFS Powertools 我在我的机器上使用的代码是 Add TfsPendingChange Ad
  • iOS 7 UIWebView 304 缓存错误,空白页

    我在具有 UIWebView 的应用程序中发现了一个问题 iOS 7 缓存了空白正文 304 响应 导致用户刷新 UIWebView 时显示空白页面 这不是良好的用户体验 我正在尝试找出如何在 iOS 端解决此问题 因为我无法控制 Amaz
  • unmodifierList 线程安全吗?

    我有一个字符串 tagList 列表 需要在多个线程之间共享以供读取 因此我创建了它的不可修改版本并将其传递给线程 我不确定它是否是线程安全的 因为线程只读取该列表 所以我猜应该可以吧 另外 当我将不可修改的列表传递给线程时 它是传递单个副
  • 将自纪元以来的时间戳转换为 datetime.datetime

    自纪元以来我有以下时间戳 Timestamp 1346114717972 1354087827000 如何将这些时间戳转换为某种特定的输出格式 例如mm dd yyyy hr min sec 我尝试将它们转换为datetime dateti
  • 如何为 RabbitMQ 连接设置自定义名称?

    能够通过连接名称识别 RabbitMQ 客户端将非常有用 我正在使用 Spring Cloud Streams 抽象 并且使用默认设置我得到类似的东西 如何在 Spring Boot 客户端中设置自定义 RabbitMQ 连接名称 EDIT
  • Gridview 中的 TimeSpan DataFormatString

    我有一个带有来自 linq 查询的 ObjectDataSource 的 gridview 源的变量之一是时间跨度 我将绑定字段与 DataField MyTimeSpanVariable 绑定 数据包含以秒和分钟为单位的时间 很少以小时为
  • EF5 收到此错误消息:无法检查模型兼容性,因为数据库不包含模型元数据

    每次运行该应用程序时 都会显示此错误消息 我正在使用实体Framework 5 Code First 这是错误消息 System NotSupportedException Model compatibility cannot be che
  • 分布式 Elixir 示例不起作用

    我有一个非常简单的 Elixir 代码示例 我想在不同的节点上运行 第一个节点位于我的笔记本电脑上 第二个节点是 Raspberry Pi 通过 SSH 访问 代码很简单 node1 my computer defmodule Hello
  • Visual Studio 和 SQL Server - 安装顺序正确吗?

    我正在重建我的开发机器 这个问题对我来说并不新鲜 但我不记得解决方案 我从 SQL 2008 Developer 开始 然后是 VS 2008 Pro SQL SP1 VS SP1 结果是我无法打开SSIS项目 参见下面的错误 正确的顺序是
  • 监听 Flutter 中的 API 变化

    假设我有一个 API 它提供一个返回 id 和名称的 JSON 响应 在移动应用程序中 通常我会发出一个 http GET 响应 以便在与服务器的一次性连接中获取此数据 并在应用程序中显示结果 但是 如果数据随着时间的推移而变化 并且我想在
  • 如何在asp.net中显示Page_Load函数中设置的变量值

    我有一个从数据库获取的变量 我想在 html 之间的 aspx 页面中输出该变量 我试图将其公开 但它显示一些错误 如何在其 aspx 页面中使用页面加载函数中设置的变量 第一种方式 您将 Literal 控件放置在要显示变量的位置 然后在
  • 带有选项的简单选择标签在 Chrome 上不起作用

    我遇到了这个问题 我无法在我的 chrome 上扩展这个简单的选择标签
  • 在应用程序中使用多个网络接口

    我编写了一个应用程序 通过 wifi 触发索尼 qx 智能手机可连接相机 但是 我需要通过另一个本地网络实时传输手机上的图像 由于 wifi 卡用于 qx 连接 我需要能够通过 USB 使用以太网从手机传输图像 HTTP 请求将用于触发相机
  • 当手动将进度设置为 MotionLayout 时,它会清除所有约束

    我有带有两个小部件的 MotionLayout 一个在 MotionLayout 中描述 第二个在场景文件中描述 布局文件
  • 如何获取用户控件数据类型所在的TabPage

    我正在使用用户控件包装器方法构建自定义数据类型 我在其中添加现有的 TinyMCE 数据类型 问题是我需要找到一种方法来动态获取数据类型所在的当前 TabPage 以便我可以将 TinyMCE 按钮添加到菜单中 这就是我目前所拥有的 Tab
  • 使用 Ajax 和 PHP $_FILES 从 Canvas 元素发送图像

    我需要能够将图像和一些表单字段从客户端画布元素发送到 PHP 脚本 最终以 POST 和 FILES 结束 当我这样发送时