使用ASP.NET Core v.2.1.2和AWSSDK for S3(版本3.3.20.2)
相同的控制器,两个不同的路由(一个有url param而另一个没有)。方法是相同的,除了url param有一个参数。我想上传一个文件,然后将其发送到S3(这在无参数情况下工作正常)。
只是添加id参数会导致aws的请求因错误而超时:
"Your socket connection to the server was not read from or written to within the timeout period. Idle connections will be closed."
这是失败的请求:
curl -X POST \
http://localhost:5000/api/post/image/4 \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Postman-Token: c78c7572-8822-4de7-a532-61538df87c85' \
-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
-F =@/Users/myusername/Desktop/peace.png
我想添加id参数会改变HttpContext.Request.Body,但是当我在调试中运行并添加断点时,我看不到这种变化(流看起来完全一样)
我在这里错过了什么?相同的代码但删除了id param适用于两个路由
顺便说一下,我希望id param存在的原因是,一旦上传文件,我就可以在帖子上记录文件ID作为对AWS中记录的引用
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using BlogApi.Models;
using BlogApi.Services;
namespace BlogApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class PostController : ControllerBase
{
public string AWS_KEY {get; private set;}
public string AWS_SECRET {get; private set;}
private readonly PostContext _context;
private AmazonUploader uploader { get; set; }
public PostController(PostContext context)
{
_context = context;
AWS_KEY = "my_key";
AWS_SECRET = "my_secret";
uploader = new AmazonUploader(AWS_KEY, AWS_SECRET);
}
[HttpPost("image/{id}")]
public string Image(long id)
{
var request = HttpContext.Request;
var fileStream = request.Body;
var contentLength = request.ContentLength;
var contentType = request.ContentType;
string key = Guid.NewGuid().ToString();
var length = contentLength.HasValue ? (long)contentLength : 0;
return uploader.sendMyFileToS3(fileStream, contentType, length, key).Result;
}
[HttpPost]
public string MyFileUpload()
{
var request = HttpContext.Request;
var fileStream = request.Body;
var contentLength = request.ContentLength;
var contentType = request.ContentType;
string key = Guid.NewGuid().ToString();
var length = contentLength.HasValue ? (long)contentLength : 0;
return uploader.sendMyFileToS3(fileStream, contentType, length, key).Result;
}
...
仅供参考,这是我的AmazonUploader类的代码
using System;
using System.Diagnostics;
using System.Net;
using System.Threading.Tasks;
using System.IO;
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
using Microsoft.Extensions.Configuration;
namespace BlogApi.Services
{
public class AmazonUploader
{
private IAmazonS3 client;
private const string bucketName = "my_bucket";
private static readonly RegionEndpoint bucketRegion = RegionEndpoint.EUWest2;
public AmazonUploader(string AWS_KEY, string AWS_SECRET) {
client = new AmazonS3Client(AWS_KEY, AWS_SECRET, bucketRegion);
}
public async Task<ListObjectsResponse> ListingObjectsAsync()
{
ListObjectsRequest request = new ListObjectsRequest
{
BucketName = bucketName
};
return await client.ListObjectsAsync(request);
}
public async Task<string> sendMyFileToS3(System.IO.Stream inputStream, string contentType, long contentLength, string key)
{
PutObjectRequest request = new PutObjectRequest
{
BucketName = bucketName,
Key = key,
ContentType = contentType,
InputStream = inputStream
};
request.Headers.ContentLength = contentLength;
PutObjectResponse awsResponse = await client.PutObjectAsync(request);
if (awsResponse.HttpStatusCode == HttpStatusCode.OK) {
return key;
} else {
return "error";
}
}
}
}
我刚刚发现了问题
a)我犯了一个错误,并且不知何故Postman添加了一个额外的Content-Type标题:application / x-www-form-encoded
b)即使我没有错误地添加该标题,实际的内容类型也是错误的 - 我发送的是multipart / form-data,它不起作用 - 我需要将它作为二进制文件发送。如果我在Postman中为请求的Body选择了该选项,它就可以工作。