我有以下应用程序从amazons Sponsored Products API下载productAds
文档:https://advertising.amazon.com/API/docs/reference/reports
当我尝试使用它时,我从请求报告中获得响应,并在s3 Bucket中获取文件。
server is running at localhost:3000
{"reportId":"amzn1.clicPI.v1.p7.5B7EE.d141f-e5-4b-a8-6a4e712","status":"SUCCESS","statusDetails":"Report has been successfully generated","location":"https://advertising-api.amazon.com/v1/reports/amzn1.clsAPI.v1.p7.5B7EE.d151f-e5-4b-a8-699e712/download","fileSize":22}
和休息我得到以下错误:
donwloading <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidArgument</Code><Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message><ArgumentName>Authorization</ArgumentName><ArgumentValue>bearer Atza|IwEBIJvCt20TUi122srkN4JCOdUxlBNuLJBrtbIGF9x5QbKG67f-K-0L4RkLzeyouXWy_U_-VscaCe1aFqOJK55X9Mu2X6nwWkAWRyhc6cCMfPjKpyyVjKtPqC8Plme84om1dqtmIqC93yUVc_clHimQqmnl262te2EXyUhYoVQg8hK2nlDG67Iw7xjsLK4rgl3E4RR36DHnZkEOnVQZtfjIkIbcYtsCSAdpRZRazF4FQfpS-jHvMlwuH8TZfY9tRpmBEx5fjJw1WZ14Dejqti23mZ7yt-MjNkUuD-DdPXs3fek1ZJePlHEVzcI2y_WzCnwJnoSVp5a5w1WgNco8YqEGEuLsT9S0dxQRluTiw8f4b4lx2FFFm9jz0K7pqo1Mvs6DZOVCDJzE-xJ_VLlWoE5QDMUAMor4AEQH44_0NWBjJDrYaVvn1vZLCER1uxW4jgr127W5yXaj4y1vj_vADwFq9a3330hAc73EWwL6FFSfoTQZyNc4Fh1d3DXfVHpXFk6cv0bHt4cV_OotGwGHat5fv75VHX5K3al3Xd5-QJv2cTiQ9srY5oqKsdbxptGaxAdrdMQaUlFHhyHEGbwED9xYoCw6-IauN15gvMAei9wz2kzRCA</ArgumentValue><RequestId>BDCE812C4363E9D2</RequestId><HostId>4ixH24mPtMBt+FDnI3rM9UJP95toaNBmmR1v0uQJ5XkyiXbtLEuZ8d+vDI0+gquwhn6/Fkz6/+o=</HostId></Error>
这是应用程序。如何下载报告并正确传递标题?我在PHP中发现了这个具有下载功能的repo:https://github.com/dbrent-amazon/amazon-advertising-api-php/blob/master/AmazonAdvertisingApi/Client.php
const express = require('express')
const app = express();
const request = require('request');
const moment = require('moment');
const fs = require('fs')
const path = require('path')
const config = require('./config')
const auth = require('./helpers/auth');
const cron = require('./helpers/cron');
const con = require('./helpers/database');
const getProfiles = (headers) => {
return new Promise((resolve, reject) => {
request({
url: config.ad_url + '/v1/profiles',
method: "GET",
headers: headers
}, (err, httpResponse, body) => {
if (err) {
reject(err);
}
resolve(body);
});
})
}
const createReport = (params, recordType, headers) => {
return new Promise((resolve, reject) => {
request({
url: config.ad_url + '/v1/' + recordType + '/report',
method: "POST",
headers: headers,
json: params
}, (err, httpResponse, body) => {
if (err) {
reject(err);
}
resolve(body);
});
})
}
const getReport = (reportId, headers) => {
return new Promise((resolve, reject) => {
request({
url: config.ad_url + '/v1/reports/' + reportId,
method: "GET",
headers: headers
}, (err, httpResponse, body) => {
if (err) {
reject(err);
}
resolve(body);
});
})
}
function download(fileUrl, apiPath, callback) {
var url = require('url'),
http = require('http'),
p = url.parse(fileUrl),
timeout = 10000;
var file = fs.createWriteStream(apiPath);
var timeout_wrapper = function (req) {
return function () {
console.log('abort');
req.abort();
callback("File transfer timeout!");
};
};
console.log('before');
var request = http.get(fileUrl).on('response', function (res) {
console.log('in cb');
var len = parseInt(res.headers['content-length'], 10);
var downloaded = 0;
res.on('data', function (chunk) {
file.write(chunk);
downloaded += chunk.length;
process.stdout.write("Downloading " + (100.0 * downloaded / len).toFixed(2) + "% " + downloaded + " bytes" + isWin ? "\033[0G" : "\r");
// reset timeout
clearTimeout(timeoutId);
timeoutId = setTimeout(fn, timeout);
}).on('end', function () {
// clear timeout
clearTimeout(timeoutId);
file.end();
console.log(file_name + ' downloaded to: ' + apiPath);
callback(null);
}).on('error', function (err) {
// clear timeout
clearTimeout(timeoutId);
callback(err.message);
});
});
// generate timeout handler
var fn = timeout_wrapper(request);
// set initial timeout
var timeoutId = setTimeout(fn, timeout);
}
const recordType = 'productAds';
const campaignType = 'sponsoredProducts';
const reportDate = moment().format('YYYYMMDD');
const metrics = 'campaignId,sku,currency,attributedConversions1d';
const reportParam = {
campaignType: campaignType,
// segment: "query",
reportDate: reportDate,
metrics: metrics
}
auth().then(res => {
const headers = {
'Content-Type': 'application/json',
'Authorization': config.token_type + ' ' + res.access_token,
'Amazon-Advertising-API-Scope': '196354651614',
}
// getProfiles(headers).then(res => {})
const reportId = 'amzn1.clicksAI.1.p.5B057EE.d41f-e5-4a-a8-699e712';
getReport(reportId, headers).then(res => {
console.log(res)
const file = JSON.parse(res);
// console.log(file.location )
// download
request({
url: file.location,
method: 'GET',
headers: {
'Authorization': headers.Authorization,
'Amazon-Advertising-API-Scope': '196335474',
'Allow': 'GET, HEAD, PUT, DELETE'
}
}, (err, response, body) => {
console.log('donwloading', body)
})
})
createReport(reportParam, recordType, headers).then(res => {
const reportId = 'amzn1.clicksI.v1.p7.5B07EE.d1541f-e5-eb-a68-6996e712';
})
})
app.listen(3000, function(err) {
console.log("server is running at localhost:3000");
})
答案 0 :(得分:0)
这是由于将“ Authorization”标头发送到S3而引起的,它不希望这样做。原因是因为来自API的/ download响应是307重定向,所以您正在使用的客户端使用完整的API标头进行重定向。要解决此问题,请防止客户端遵循重定向并改为从响应的标题解析S3位置。