如何将 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 个简单查询并一次全部执行(或者一个一个执行,如果你这么说的话)是这里的最佳选择。
我已经阅读了几乎所有有关从计算机中的 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 个简单查询并一次全部执行(或者一个一个执行,如果你这么说的话)是这里的最佳选择。