我是AWS S3的新手,并尝试通过分块过程上传大文件。从UI,我将文件的分块数据(blob)发送到WCF服务,从那里我将使用MultiPartAPI将其上传到S3。 请注意,文件可以以GB为单位。这就是为什么我要制作文件的一部分并将其上传到S3的原因。
public UploadPartResponse UploadChunk(Stream stream, string fileName, string uploadId, List<PartETag> eTags, int partNumber, bool lastPart)
{
stream.Position = 0; // Throwing Exceptions
//Step 1: build and send a multi upload request
if (partNumber == 1)
{
var initiateRequest = new InitiateMultipartUploadRequest
{
BucketName = _settings.Bucket,
Key = fileName
};
var initResponse = _s3Client.InitiateMultipartUpload(initiateRequest);
uploadId = initResponse.UploadId;
}
//Step 2: upload each chunk (this is run for every chunk unlike the other steps which are run once)
var uploadRequest = new UploadPartRequest
{
BucketName = _settings.Bucket,
Key = fileName,
UploadId = uploadId,
PartNumber = partNumber,
InputStream = stream,
IsLastPart = lastPart,
PartSize = stream.Length // Throwing Exceptions
};
var response = _s3Client.UploadPart(uploadRequest);
//Step 3: build and send the multipart complete request
if (lastPart)
{
eTags.Add(new PartETag
{
PartNumber = partNumber,
ETag = response.ETag
});
var completeRequest = new CompleteMultipartUploadRequest
{
BucketName = _settings.Bucket,
Key = fileName,
UploadId = uploadId,
PartETags = eTags
};
try
{
_s3Client.CompleteMultipartUpload(completeRequest);
}
catch
{
//do some logging and return null response
return null;
}
}
response.ResponseMetadata.Metadata["uploadid"] = uploadRequest.UploadId;
return response;
}
在这里, stream.Position = 0 和 stream.Length 引发如下异常:
在System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream.get_Length()
然后我看到 stream.CanSeek 是 false 。
我是否需要缓冲整个流,并提前将其加载到内存中以使其正常工作?
更新:我正在做下面的事情,它正在工作,但是不知道它是否有效。
var ms = new MemoryStream();
stream.CopyTo(ms);
ms.Position = 0;
还有其他方法吗?预先感谢。
答案 0 :(得分:0)
这是一种公平的方法,但是我选择了另一种方法,即使用签名的URL直接上传到S3。这样做的好处是减轻了服务器的负担,并减少了数据传输。
根据您的应用程序,可能值得考虑以下内容:
在C#中获取预签名URL:
public string GetPreSignedUrl(string bucketName, string keyPrefix, string fileName)
{
var client = new AmazonS3Client(_credentials, _region);
var keyName = $"{keyPrefix}/{fileName}";
var preSignedUrlRequest = new GetPreSignedUrlRequest()
{
BucketName = bucketName,
Key = keyName,
Expires = DateTime.Now.AddMinutes(5),
Protocol = (Protocol.HTTPS)
};
return client.GetPreSignedURL(preSignedUrlRequest);
}
这将为客户端创建一个URL,以将其直接上传到S3,您需要将其传递到UI。然后,您可以使用分段上传到预先签名的网址。
以下是使用焦虑进行分段上传的一个很好的示例:https://github.com/prestonlimlianjie/aws-s3-multipart-presigned-upload/blob/master/frontend/pages/index.js
答案 1 :(得分:0)
有点晚了,但是请注意TransferUtility直接支持流:
https://docs.aws.amazon.com/AmazonS3/latest/dev/HLuploadFileDotNet.html