如何将 blob(AJAX 响应)保存到命名文件(JSON 类型)到我的服务器而不是用户计算机中

How to save a blob (AJAX response) into a named file (JSON type) into my server NOT in user computer

我已经阅读了几乎所有有关从计算机中的 blob 创建(或下载)URL 的主题,但是,我需要一些不同的东西:

(1) 将自己服务器中的blob保存到JSON文件中,然后

(2) 优化使用存储在JSON.

中的数据更新数据库的方式

我尝试了以下所有代码变体,但均未成功

var blob = new Blob(response, { type: contentType });
var file = new File([blob], filename, {type: contentType, lastModified: Date.now()});

其中 响应 是来自下面代码的 解析JSON

如果服务器中已经有一个内容为空的文件,打开它并从 blob 更新它(然后关闭它)会更好吗?

我的目的是将 AJAX 查询(来自 API)的响应内容下载到我的服务器(而不是浏览器中的任何客户端计算机),然后更新相应的值数据库 table.

用例如下:我使用 cron 从 API 收到价目表(约 40,000 件),然后我必须更新服务器数据库中的产品价格。

让我们看下面的代码:

<div id="app">
    <p style="text-align: center; margin-top: 50px;">
        <i class="fa fa-spinner fa-spin" style="font-size: 15px;"></i><br>
        please wait to load the list of items here...
    </p>
</div>

<script>
var settings = {
  "url": "https://www.notimportant/etc/",
  "method": "GET",
  "timeout": 0,
  "headers": {
    "GUID": "something"
  },
};


$.ajax(settings).done(function(response) {
  var parsedJSON = JSON.parse(response);
  
                                                  console.log(parsedJSON[0]); /* <= to see the structure of each object in the response array */
console.log('total items: ' + parsedJSON.length);
  
   var template = `
<p>List of items</p>
{{#each this}}
<div>{{plusOne @index}} - Code: {{ProductCode}} - Name: {{ProductName}} - Price: {{ProductPrice}}</div>
{{/each}}
`;

Handlebars.registerHelper('plusOne', function(index) {
    index++;
    return index;
});
  var show = Handlebars.compile(template);
  $('#app').html(show(parsedJSON));
});
        </script>

到目前为止一切顺利,我可以使用 Handlebars JS 检查浏览器中的结果(也可以在控制台中查看从 API 接收到的对象结构)。然而,我的目的是使用数组 parsedJSON 中的每个对象来更新 table 中的值。我可以做一些

for(i = 0; i < parsedJSON.length; i++) { // use here $.post to send ProductCode, ProductName and ProductPrice to a php file where I execute a query to update each product into the database

var ProductCode = parsedJSON[i].ProductCode;
var ProductName = parsedJSON[i].ProductName;
var ProductPrice = parsedJSON[i].ProductPrice;

  $.post("update_db.php", {code: ProductCode, name: ProductName, price: ProductPrice}, function(data, status){
    console.log("Product " + ProductCode + " update = " + status);
  });
}

alert("all products' update was finished");

但是,这会在我的数据库中创建大约 40,000 个单个查询(这根本不行)。

我宁愿将数组 保存在服务器 中(要保存响应 blob,从中创建一个文件,将其命名为 myJSONfile.json,然后在 php 中使用 $myfileaddress = $base + "myJSONfile.json",使用 $myfile = file_get_contents($myfileaddress) 读取它,然后 $myJson = json_decode($myfile, true) 然后使用 foreach($array as $item) {// update each row in products table in database 更新数据库,等等。 }

但是我怀疑我是否可以 运行 具有 40,000 个组件的多查询(或者一个那么大的准备好的语句,即使我大大增加了允许的内存 - 我宁愿不这样做)。如果我错了请解释原因。

目前,我的代码只是一个一个地发送查询,这不是我会一直做的事情(我最好只使用 PHP 或只使用 JavaScript 来创建到数据库的单个连接,目前还不多。

我实际上收到了几乎即时的响应 - 警报 所有产品的更新已完成 以获取完整的产品列表,但随后 PHP 响应消息不断出现控制台也是,在相当长的一段时间内成功更新每一行(谈论几分钟)这不是我所期望的。

我会使用一些优雅的东西,假设在单个事务中使用 500 个查询(并且只需 80 个步骤即可完成整个更新,而不是完整的 40,000 个简单查询),但不确定如何正确设置所有内容。

我下载完整的 JSON 而不是通过单独的 API 请求(加上更新)更新每个产品的目的是只查询一次外部服务器(使用 cron)而不是很多次,而是在我自己的服务器上对数据进行进一步处理。在实际情况下,每个产品都来自 API,大约有 20 个参数,而不仅仅是 3 个(代码、名称和价格),但这与所讨论的问题无关。 (另外,对于单独片段中显示的代码中的一些小疏忽,我深表歉意,但我输入的速度很快,而不是从生产文件中复制粘贴——我现在不是在我从事相关项目的计算机上写作)。

最终编辑

我终于在下面编写了更紧凑的代码,它工作得很好(使用 UPDATE 准备好的语句)。我不会将其作为单独的答案发布,而是将其插入此处:

<?php
$servername = "localhost";
$username = "someuser";
$password = "somepassw";
$dbname = "somedb";

// requiring data from API

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://www.notimportant/etc/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS =>"{\"name\": null, \"stores\": null, \"products\": []}",
  CURLOPT_HTTPHEADER => array(
    "GUID: something",
    "Content-Type: application/json"
  ),
));

$response = curl_exec($curl);

curl_close($curl);

// echo $response;
$data = json_decode($response);
echo "Product count: " . count($data) . "<br>\n";
echo "Preparing to save products to database... <br>\n";

// end receiving data from API

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

// prepare and bind
$stmt = $conn->prepare("UPDATE `my_table` SET `price` = ?, `stock` = ? WHERE `my_table`.`product_id` = ?"); 
$stmt->bind_param("dii", $price, $stock, $id);

// set parameters and execute
foreach($data as $productInfo) {
    $price = $productInfo->RetailPrice;
    $stock = $productInfo->Stock;
    $id = $productInfo->ProductId;
    $stmt->execute();
}

echo "Update was ok";

$stmt->close();
$conn->close();

?>

@Bravemaster 的建议很有帮助,代码 运行 现在不到 10 秒,所以它是目前接受 table 的解决方案。第 (2) 点已经很好地解决了,并且 (1) 似乎不再有用了(因为同时使用 file_put_contents[= 是没有意义的82=])。我还将 Bravemaster 的输入投票作为可接受的答案 - 因为他对我的代码做出了慷慨的贡献。所有 40k+ 查询都在一个批次中顺利进行。剩下的就是添加更多的数据验证(为了安全起见)和设置 cron 进程(不是真正的问题)。

您不需要在客户端post中再次从外部API获取数据 到您的服务器。

PHP 可以发送获取请求并接收响应 而无需 jQuery.

您可以编写 php 脚本从外部 API 获取产品价目表,如下所示:

$url = "https://www.notimportant/etc/";
$header = ['GUID' => 'something']

echo "Sending request to API server...\n";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_HEADER, $header);
$response = curl_exec($ch);
echo "Received response\n";
curl_close($ch);

$data = json_decode($response);
echo "Product count: " . count($data) . "\n";
echo "Saving products to database...";
foreach($data as $productInfo) {
   save_data($productInfo); // you need to implement save_data
}
echo "Products saved. Exiting"\n;
exit(0);

如果您想知道如何将字符串(在本例中为JSON 响应)写入文件,请参阅:How to put the a string into a text file in PHP?

如果您想知道如何使用准备好的语句执行MySQL查询,请参阅:How can I prevent SQL injection in PHP?

如果您想知道如何使用自定义 header 发送 https 请求,请参阅此 post:Send GET HTTPS request with custom headers PHP

如果您想知道如何使用 crontab 定期执行 php 脚本,请参阅此 post:Running PHP file using crontab

(Don't worry,都是Whosebug posts)

I would use something elegant, let's say to use 500 queries in a single transaction (and make the entire update in just 80 steps instead of a full 40,000 simple queries), but not sure how to set everything right.

事务不会提高性能,事务从来不是为了性能而是为了数据完整性。进行 40,000 个简单查询并一次全部执行(或者一个一个执行,如果你这么说的话)是这里的最佳选择。