我在使用图像上传功能时遇到一些困难,我希望有人已经知道答案......我正在按照以下步骤操作:
POST
初始化上传(并获取上传 URL)PUT
图片上传网址GET
图像的状态(轮询直到AVAILABLE
或PROCESSING_FAILED
)content.media
或 content.multiImage
中。我可靠地获得了
PROCESSING_FAILED
的图像状态,因此我在步骤 3 处停止。我将在下面分享更多详细信息,我很高兴获得任何人的见解...谢谢!
我正在使用 RestSharp 库使用 C# 进行工作,但我在做什么应该非常清楚,因此如果您可以在我的方法中看到错误,那么您熟悉哪种语言可能并不重要。 ..
我的应用程序已被授予访问 Community Management API(开发层)的权限,并且我正在使用具有
w_member_social
和 w_organization_social
范围的令牌。
我拥有我要发布到的页面,并且该页面的组织骨灰盒是正确的。
我正在使用这些文档页面:
在可能的情况下,我通过内联字符串等简化了下面的代码,因此更容易看到我在做什么...
首先,我使用最常用的基本 url 初始化客户端:
var client = new RestClient("https://api.linkedin.com/rest");
var imgRequest = new RestRequest($"images?action=initializeUpload", Method.Post);
imgRequest.AddHeader("Authorization", $"Bearer {token}");
imgRequest.AddHeader("Content-Type", "application/json");
imgRequest.AddHeader("X-Restli-Protocol-Version", "2.0.0");
imgRequest.AddHeader("LinkedIn-Version","202309");
var imgRequestBody = new { initializeUploadRequest = new { owner = author }};
imgRequest.AddJsonBody(imgRequestBody);
var imgResponse = await client!.ExecuteAsync(imgRequest);
这会返回成功响应,我可以从 JSON 中提取 URL:
var imgResponseData = JsonConvert.DeserializeObject<LinkedInImageResponse>(imgResponse.Content!);
var uploadUrl = imgResponseData!.value.uploadUrl;
using (var uploadClient = new RestClient())
{
var uploadRequest = new RestRequest(uploadUrl, Method.Put); // PUT is correct
uploadRequest.AddHeader("Authorization", $"Bearer {token}");
uploadRequest.AddHeader("Content-Type", "image/png"); // TODO: get this from the image
// uploadRequest.AddHeader("X-Restli-Protocol-Version", "2.0.0");
// uploadRequest.AddHeader("LinkedIn-Version","202309");
var imgUploadStream = await image.GetStreamAsync();
uploadRequest.AddFile($"image_{++iCounter}", () => imgUploadStream, image.Filename);
var uploadResponse = await uploadClient.ExecuteAsync(uploadRequest);
if (!uploadResponse.IsSuccessful) throw new Exception(); // simplified
}
这会返回成功响应,因此我相信图像已成功上传。
事情开始变得有点不对劲......
var imageOk = false;
do
{
Thread.Sleep(5000); // 5s poll... (ugh!)
var pollRequest = new RestRequest($"images/{imgResponseData!.value.image}", Method.Get);
pollRequest.AddHeader("Authorization", $"Bearer {token}");
pollRequest.AddHeader("LinkedIn-Version","202309");
var pollResponse = await client!.ExecuteAsync(pollRequest);
var pollData = JsonConvert.DeserializeObject<LinkedInPollResponse>(pollResponse.Content!);
imageOk = pollData?.status == "AVAILABLE";
var imageFailed = pollData?.status == "PROCESSING_FAILED";
if (imageFailed) { throw new Exception($"Image status for post {t}: {pollData?.status}", new Exception(Summarise(pollRequest, null) + Summarise(pollResponse))); }
if (++attempts > 5) throw new Exception($"Cannot poll image status for post {t} - too many attempts");
} while (!imageOk);
这再次使用公共客户端,并在步骤 0 中初始化基本 url。
我收到请求的
200
(成功)响应,内容包含状态 PROCESSING_FAILED
:
{
"owner":"urn:li:organization:19321500",
"status":"PROCESSING_FAILED",
"id":"urn:li:image:D4E10AQHZqWNBn_7gOQ"
}
文档说:
PROCESSING_FAILED - 由于客户端错误(例如文件大小太大、文件格式不受支持、内部错误(例如性能问题、数据库错误、网络故障)或其他问题)而导致处理失败。
该图像是小 (291kb) PNG 尺寸:432x430。如果它有任何问题,我会感到惊讶 - 它在正常情况下(包括手动创建帖子时)呈现良好。
如果有任何见解,我将不胜感激......
橡皮鸭相当激烈地避开了整个事情,我在搜索中尝试了更多关键字,并从j4rey找到了这个解决方案,它回答了问题。
TLDR:问题是我使用
uploadRequest.AddFile
包含了该文件 - 它将其作为 表单帖子 的一部分包含在内。 LinkedIn 希望文件为二进制内容。
这是我对其代码的改编 - 效果完美:
using (var uploadClient = new HttpClient())
{
uploadClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var imageDataStream = await image.GetStreamAsync();
var uploadContent = new StreamContent(imageDataStream);
var uploadResponse = await uploadClient.PutAsync(uploadUrl, uploadContent);
if (!uploadResponse.IsSuccessStatusCode) throw new Exception($"Cannot upload image for post {t}", new Exception(Summarise(uploadResponse)));
}
(注意。我不再使用 RestSharp 进行上传 - 无论如何,这并不是一个真正令人放松的操作,并且
HttpClient
是一个熟悉的朋友。)