* LCFile.cs:
* FileTest.cs: * LCQiniuUploader.cs: * LCProgressableStreamContent.cs: * LCAWSUploader.cs: chore: 支持文件保存进度
parent
4df8179e5a
commit
0809a9c558
|
@ -7,6 +7,7 @@ using LeanCloud.Storage;
|
|||
namespace LeanCloud.Test {
|
||||
public class FileTest {
|
||||
static readonly string AvatarFilePath = "../../../assets/hello.png";
|
||||
static readonly string APKFilePath = "../../../assets/test.apk";
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() {
|
||||
|
@ -31,7 +32,9 @@ namespace LeanCloud.Test {
|
|||
[Test]
|
||||
public async Task SaveFromPath() {
|
||||
LCFile file = new LCFile("avatar", AvatarFilePath);
|
||||
await file.Save();
|
||||
await file.Save((count, total) => {
|
||||
TestContext.WriteLine($"progress: {count}/{total}");
|
||||
});
|
||||
TestContext.WriteLine(file.ObjectId);
|
||||
Assert.NotNull(file.ObjectId);
|
||||
}
|
||||
|
@ -60,7 +63,7 @@ namespace LeanCloud.Test {
|
|||
|
||||
[Test]
|
||||
public async Task Qiniu() {
|
||||
LCFile file = new LCFile("avatar", AvatarFilePath);
|
||||
LCFile file = new LCFile("avatar", APKFilePath);
|
||||
await file.Save();
|
||||
TestContext.WriteLine(file.ObjectId);
|
||||
Assert.NotNull(file.ObjectId);
|
||||
|
@ -70,7 +73,7 @@ namespace LeanCloud.Test {
|
|||
public async Task AWS() {
|
||||
Logger.LogDelegate += Utils.Print;
|
||||
LeanCloud.Initialize("UlCpyvLm8aMzQsW6KnP6W3Wt-MdYXbMMI", "PyCTYoNoxCVoKKg394PBeS4r", "https://ulcpyvlm.api.lncldglobal.com");
|
||||
LCFile file = new LCFile("avatar", "../../../assets/hello.png");
|
||||
LCFile file = new LCFile("avatar", APKFilePath);
|
||||
await file.Save();
|
||||
TestContext.WriteLine(file.ObjectId);
|
||||
Assert.NotNull(file.ObjectId);
|
||||
|
|
|
@ -19,11 +19,13 @@ namespace LeanCloud.Storage.Internal.File {
|
|||
this.data = data;
|
||||
}
|
||||
|
||||
internal async Task Upload(Action<int, int> onProgress) {
|
||||
internal async Task Upload(Action<long, long> onProgress) {
|
||||
LCProgressableStreamContent content = new LCProgressableStreamContent(new ByteArrayContent(data), onProgress);
|
||||
|
||||
HttpRequestMessage request = new HttpRequestMessage {
|
||||
RequestUri = new Uri(uploadUrl),
|
||||
Method = HttpMethod.Put,
|
||||
Content = new ByteArrayContent(data)
|
||||
Content = content
|
||||
};
|
||||
HttpClient client = new HttpClient();
|
||||
request.Headers.CacheControl = new CacheControlHeaderValue {
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LeanCloud.Storage.Internal.File {
|
||||
internal class LCProgressableStreamContent : HttpContent {
|
||||
const int defaultBufferSize = 5 * 4096;
|
||||
|
||||
readonly HttpContent content;
|
||||
|
||||
readonly int bufferSize;
|
||||
|
||||
readonly Action<long, long> progress;
|
||||
|
||||
internal LCProgressableStreamContent(HttpContent content, Action<long, long> progress) : this(content, defaultBufferSize, progress) { }
|
||||
|
||||
internal LCProgressableStreamContent(HttpContent content, int bufferSize, Action<long, long> progress) {
|
||||
if (content == null) {
|
||||
throw new ArgumentNullException("content");
|
||||
}
|
||||
if (bufferSize <= 0) {
|
||||
throw new ArgumentOutOfRangeException("bufferSize");
|
||||
}
|
||||
|
||||
this.content = content;
|
||||
this.bufferSize = bufferSize;
|
||||
this.progress = progress;
|
||||
|
||||
foreach (var h in content.Headers) {
|
||||
Headers.Add(h.Key, h.Value);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) {
|
||||
|
||||
return Task.Run(async () => {
|
||||
var buffer = new byte[bufferSize];
|
||||
TryComputeLength(out long size);
|
||||
var uploaded = 0;
|
||||
|
||||
using (var sinput = await content.ReadAsStreamAsync()) {
|
||||
while (true) {
|
||||
var length = sinput.Read(buffer, 0, buffer.Length);
|
||||
if (length <= 0) break;
|
||||
|
||||
uploaded += length;
|
||||
progress?.Invoke(uploaded, size);
|
||||
|
||||
stream.Write(buffer, 0, length);
|
||||
stream.Flush();
|
||||
}
|
||||
}
|
||||
stream.Flush();
|
||||
});
|
||||
}
|
||||
|
||||
protected override bool TryComputeLength(out long length) {
|
||||
length = content.Headers.ContentLength.GetValueOrDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing) {
|
||||
if (disposing) {
|
||||
content.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,11 +22,14 @@ namespace LeanCloud.Storage.Internal.File {
|
|||
this.data = data;
|
||||
}
|
||||
|
||||
internal async Task Upload(Action<int, int> onProgress) {
|
||||
MultipartFormDataContent content = new MultipartFormDataContent();
|
||||
content.Add(new StringContent(key), "key");
|
||||
content.Add(new StringContent(token), "token");
|
||||
content.Add(new ByteArrayContent(data), "file");
|
||||
internal async Task Upload(Action<long, long> onProgress) {
|
||||
MultipartFormDataContent dataContent = new MultipartFormDataContent();
|
||||
dataContent.Add(new StringContent(key), "key");
|
||||
dataContent.Add(new StringContent(token), "token");
|
||||
dataContent.Add(new ByteArrayContent(data), "file");
|
||||
|
||||
LCProgressableStreamContent content = new LCProgressableStreamContent(dataContent, onProgress);
|
||||
|
||||
HttpRequestMessage request = new HttpRequestMessage {
|
||||
RequestUri = new Uri(uploadUrl),
|
||||
Method = HttpMethod.Post,
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||
using System.Threading.Tasks;
|
||||
using LeanCloud.Storage.Internal.File;
|
||||
using LeanCloud.Storage.Internal.Object;
|
||||
using LeanCloud.Common;
|
||||
|
||||
namespace LeanCloud.Storage {
|
||||
public class LCFile : LCObject {
|
||||
|
@ -67,7 +68,7 @@ namespace LeanCloud.Storage {
|
|||
MetaData[key] = value;
|
||||
}
|
||||
|
||||
public async Task<LCFile> Save() {
|
||||
public async Task<LCFile> Save(Action<long, long> onProgress = null) {
|
||||
if (!string.IsNullOrEmpty(Url)) {
|
||||
// 外链方式
|
||||
await base.Save();
|
||||
|
@ -81,11 +82,11 @@ namespace LeanCloud.Storage {
|
|||
if (provider == "s3") {
|
||||
// AWS
|
||||
LCAWSUploader uploader = new LCAWSUploader(uploadUrl, MimeType, data);
|
||||
await uploader.Upload(null);
|
||||
await uploader.Upload(onProgress);
|
||||
} else if (provider == "qiniu") {
|
||||
// Qiniu
|
||||
LCQiniuUploader uploader = new LCQiniuUploader(uploadUrl, token, key, data);
|
||||
await uploader.Upload(null);
|
||||
await uploader.Upload(onProgress);
|
||||
} else {
|
||||
throw new Exception($"{provider} is not support.");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue