* FileTest.cs:
* AVFile.cs: * FileState.cs: * AVFileController.cs: chore: 简化 File 模块
parent
e6280b828d
commit
db35fa69c2
|
|
@ -28,6 +28,14 @@ namespace LeanCloudTests {
|
||||||
TestContext.Out.WriteLine($"file: {file.ObjectId}, {file.Url}");
|
TestContext.Out.WriteLine($"file: {file.ObjectId}, {file.Url}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task SaveUrl() {
|
||||||
|
AVFile file = new AVFile("test.jpg", "http://pic33.nipic.com/20131007/13639685_123501617185_2.jpg");
|
||||||
|
await file.SaveAsync();
|
||||||
|
Assert.NotNull(file.ObjectId);
|
||||||
|
TestContext.Out.WriteLine($"file: {file.ObjectId}, {file.Url}");
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Thumbnail() {
|
public async Task Thumbnail() {
|
||||||
AVFile file = await AVFile.GetFileWithObjectIdAsync("5d64ac55d5de2b006c1fe3d8");
|
AVFile file = await AVFile.GetFileWithObjectIdAsync("5d64ac55d5de2b006c1fe3d8");
|
||||||
|
|
@ -35,5 +43,14 @@ namespace LeanCloudTests {
|
||||||
TestContext.Out.WriteLine($"url: {file.Url}");
|
TestContext.Out.WriteLine($"url: {file.Url}");
|
||||||
TestContext.Out.WriteLine($"thumbnail url: {file.GetThumbnailUrl(28, 28)}");
|
TestContext.Out.WriteLine($"thumbnail url: {file.GetThumbnailUrl(28, 28)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task DeleteFile() {
|
||||||
|
await AVUser.LogInAsync("111111", "111111");
|
||||||
|
AVFile file = new AVFile("hello.png", File.ReadAllBytes("../../../assets/hello.png"));
|
||||||
|
await file.SaveAsync();
|
||||||
|
Assert.NotNull(file.ObjectId);
|
||||||
|
await file.DeleteAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,7 @@ namespace LeanCloud.Storage.Internal {
|
||||||
IProgress<AVUploadProgressEventArgs> progress,
|
IProgress<AVUploadProgressEventArgs> progress,
|
||||||
CancellationToken cancellationToken = default) {
|
CancellationToken cancellationToken = default) {
|
||||||
if (state.Url != null) {
|
if (state.Url != null) {
|
||||||
// !isDirty
|
return SaveWithUrl(state);
|
||||||
return Task<FileState>.FromResult(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetFileToken(state, cancellationToken).OnSuccess(t => {
|
return GetFileToken(state, cancellationToken).OnSuccess(t => {
|
||||||
|
|
@ -50,14 +49,45 @@ namespace LeanCloud.Storage.Internal {
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken);
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal Task<FileState> SaveWithUrl(FileState state) {
|
||||||
|
Dictionary<string, object> strs = new Dictionary<string, object> {
|
||||||
|
{ "url", state.Url.ToString() },
|
||||||
|
{ "name", state.Name },
|
||||||
|
{ "mime_type", state.MimeType },
|
||||||
|
{ "metaData", state.MetaData }
|
||||||
|
};
|
||||||
|
AVCommand cmd = null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(state.ObjectId)) {
|
||||||
|
cmd = new AVCommand {
|
||||||
|
Path = $"files/{state.ObjectId}",
|
||||||
|
Method = HttpMethod.Put,
|
||||||
|
Content = strs
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
cmd = new AVCommand {
|
||||||
|
Path = "files",
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
Content = strs
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(cmd).OnSuccess(t => {
|
||||||
|
var result = t.Result.Item2;
|
||||||
|
state.ObjectId = result["objectId"].ToString();
|
||||||
|
return state;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
internal Task<Tuple<HttpStatusCode, IDictionary<string, object>>> GetFileToken(FileState fileState, CancellationToken cancellationToken) {
|
internal Task<Tuple<HttpStatusCode, IDictionary<string, object>>> GetFileToken(FileState fileState, CancellationToken cancellationToken) {
|
||||||
string str = fileState.Name;
|
string str = fileState.Name;
|
||||||
IDictionary<string, object> parameters = new Dictionary<string, object>();
|
IDictionary<string, object> parameters = new Dictionary<string, object> {
|
||||||
parameters.Add("name", str);
|
{ "name", str },
|
||||||
parameters.Add("key", GetUniqueName(fileState));
|
{ "key", GetUniqueName(fileState) },
|
||||||
parameters.Add("__type", "File");
|
{ "__type", "File" },
|
||||||
parameters.Add("mime_type", AVFile.GetMIMEType(str));
|
{ "mime_type", AVFile.GetMIMEType(str) },
|
||||||
parameters.Add("metaData", fileState.MetaData);
|
{ "metaData", fileState.MetaData }
|
||||||
|
};
|
||||||
|
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = "fileTokens",
|
Path = "fileTokens",
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal
|
namespace LeanCloud.Storage.Internal {
|
||||||
{
|
public class FileState {
|
||||||
public class FileState
|
|
||||||
{
|
|
||||||
public string ObjectId { get; internal set; }
|
public string ObjectId { get; internal set; }
|
||||||
public string Name { get; internal set; }
|
public string Name { get; internal set; }
|
||||||
public string CloudName { get; set; }
|
public string CloudName { get; set; }
|
||||||
|
|
@ -23,5 +21,18 @@ namespace LeanCloud.Storage.Internal
|
||||||
public long completed;
|
public long completed;
|
||||||
public List<string> block_ctxes = new List<string>();
|
public List<string> block_ctxes = new List<string>();
|
||||||
|
|
||||||
|
public static FileState NewFromDict(IDictionary<string, object> dict) {
|
||||||
|
FileState state = new FileState {
|
||||||
|
ObjectId = dict["objectId"] as string,
|
||||||
|
Url = new Uri(dict["url"] as string, UriKind.Absolute)
|
||||||
|
};
|
||||||
|
if (dict.TryGetValue("name", out object name)) {
|
||||||
|
state.Name = name as string;
|
||||||
|
}
|
||||||
|
if (dict.TryGetValue("metaData", out object metaData)) {
|
||||||
|
state.MetaData = metaData as Dictionary<string, object>;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,24 +8,9 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace LeanCloud {
|
namespace LeanCloud {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// AVFile is a local representation of a file that is saved to the LeanCloud.
|
/// AVFile 存储于 LeanCloud 的文件类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <example>
|
|
||||||
/// The workflow is to construct a <see cref="AVFile"/> with data and a filename,
|
|
||||||
/// then save it and set it as a field on a AVObject:
|
|
||||||
///
|
|
||||||
/// <code>
|
|
||||||
/// var file = new AVFile("hello.txt",
|
|
||||||
/// new MemoryStream(Encoding.UTF8.GetBytes("hello")));
|
|
||||||
/// await file.SaveAsync();
|
|
||||||
/// var obj = new AVObject("TestObject");
|
|
||||||
/// obj["file"] = file;
|
|
||||||
/// await obj.SaveAsync();
|
|
||||||
/// </code>
|
|
||||||
/// </example>
|
|
||||||
public class AVFile : IJsonConvertible {
|
public class AVFile : IJsonConvertible {
|
||||||
internal static int objectCounter = 0;
|
|
||||||
internal static readonly object Mutex = new object();
|
|
||||||
private FileState state;
|
private FileState state;
|
||||||
private readonly Stream dataStream;
|
private readonly Stream dataStream;
|
||||||
private readonly TaskQueue taskQueue = new TaskQueue();
|
private readonly TaskQueue taskQueue = new TaskQueue();
|
||||||
|
|
@ -39,17 +24,13 @@ namespace LeanCloud {
|
||||||
/// <param name="mimeType">文件类型</param>
|
/// <param name="mimeType">文件类型</param>
|
||||||
/// <param name="metaData">文件源信息</param>
|
/// <param name="metaData">文件源信息</param>
|
||||||
public AVFile(string name, Stream data, string mimeType = null, IDictionary<string, object> metaData = null) {
|
public AVFile(string name, Stream data, string mimeType = null, IDictionary<string, object> metaData = null) {
|
||||||
mimeType = mimeType == null ? GetMIMEType(name) : mimeType;
|
mimeType = mimeType ?? GetMIMEType(name);
|
||||||
state = new FileState {
|
state = new FileState {
|
||||||
Name = name,
|
Name = name,
|
||||||
MimeType = mimeType,
|
MimeType = mimeType,
|
||||||
MetaData = metaData
|
MetaData = metaData
|
||||||
};
|
};
|
||||||
dataStream = data;
|
dataStream = data;
|
||||||
lock (Mutex) {
|
|
||||||
objectCounter++;
|
|
||||||
state.counter = objectCounter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -112,7 +93,10 @@ namespace LeanCloud {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region created by url or uri
|
#region created by url or uri
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据文件名,Uri,文件类型以及文件源信息
|
/// 根据文件名,Uri,文件类型以及文件源信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -128,11 +112,7 @@ namespace LeanCloud {
|
||||||
MetaData = metaData,
|
MetaData = metaData,
|
||||||
MimeType = mimeType
|
MimeType = mimeType
|
||||||
};
|
};
|
||||||
lock (Mutex) {
|
IsExternal = true;
|
||||||
objectCounter++;
|
|
||||||
state.counter = objectCounter;
|
|
||||||
}
|
|
||||||
isExternal = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -179,7 +159,7 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据文件名和 Url 创建文件
|
/// 根据文件名和 Url 创建文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">文件名</param>
|
/// <param name="name">文件名</param>
|
||||||
/// <param name="url">文件的 Url</param>
|
/// <param name="url">文件的 Url</param>
|
||||||
public AVFile(string name, string url)
|
public AVFile(string name, string url)
|
||||||
|
|
@ -189,13 +169,13 @@ namespace LeanCloud {
|
||||||
internal AVFile(FileState filestate) {
|
internal AVFile(FileState filestate) {
|
||||||
state = filestate;
|
state = filestate;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal AVFile(string objectId)
|
internal AVFile(string objectId)
|
||||||
: this(new FileState() {
|
: this(new FileState {
|
||||||
ObjectId = objectId
|
ObjectId = objectId
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
@ -243,6 +223,15 @@ namespace LeanCloud {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取缩略图
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="width">宽</param>
|
||||||
|
/// <param name="height">高</param>
|
||||||
|
/// <param name="quality">质量 1-100</param>
|
||||||
|
/// <param name="scaleToFit">等比缩放,是否裁剪</param>
|
||||||
|
/// <param name="format">格式</param>
|
||||||
|
/// <returns></returns>
|
||||||
public string GetThumbnailUrl(int width, int height,
|
public string GetThumbnailUrl(int width, int height,
|
||||||
int quality = 100, bool scaleToFit = true, string format = "png") {
|
int quality = 100, bool scaleToFit = true, string format = "png") {
|
||||||
int mode = scaleToFit ? 2 : 1;
|
int mode = scaleToFit ? 2 : 1;
|
||||||
|
|
@ -263,78 +252,37 @@ namespace LeanCloud {
|
||||||
"AVFile must be saved before it can be serialized.");
|
"AVFile must be saved before it can be serialized.");
|
||||||
}
|
}
|
||||||
return new Dictionary<string, object> {
|
return new Dictionary<string, object> {
|
||||||
{"__type", "File"},
|
{ "__type", "File"} ,
|
||||||
{ "id", ObjectId },
|
{ "id", ObjectId },
|
||||||
{"name", Name},
|
{ "name", Name },
|
||||||
{"url", Url.AbsoluteUri}
|
{ "url", Url.AbsoluteUri }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Save
|
#region Save
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the file to the LeanCloud cloud.
|
/// 保存文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="progress">The progress callback.</param>
|
/// <param name="progress">The progress callback.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
public Task SaveAsync(IProgress<AVUploadProgressEventArgs> progress = null,
|
public Task SaveAsync(IProgress<AVUploadProgressEventArgs> progress = null, CancellationToken cancellationToken = default) {
|
||||||
CancellationToken cancellationToken = default) {
|
return FileController.SaveAsync(state, dataStream, progress, cancellationToken)
|
||||||
if (isExternal)
|
.OnSuccess(t => {
|
||||||
return SaveExternal();
|
state = t.Result;
|
||||||
|
});
|
||||||
return taskQueue.Enqueue(
|
|
||||||
toAwait => FileController.SaveAsync(state, dataStream, progress, cancellationToken), cancellationToken)
|
|
||||||
.OnSuccess(t => {
|
|
||||||
state = t.Result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Task SaveExternal() {
|
|
||||||
Dictionary<string, object> strs = new Dictionary<string, object>()
|
|
||||||
{
|
|
||||||
{ "url", Url.ToString() },
|
|
||||||
{ "name", Name },
|
|
||||||
{ "mime_type", MimeType},
|
|
||||||
{ "metaData", MetaData}
|
|
||||||
};
|
|
||||||
AVCommand cmd = null;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(ObjectId)) {
|
|
||||||
cmd = new AVCommand {
|
|
||||||
Path = $"files/{ObjectId}",
|
|
||||||
Method = HttpMethod.Put,
|
|
||||||
Content = strs
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
cmd = new AVCommand {
|
|
||||||
Path = "files",
|
|
||||||
Method = HttpMethod.Post,
|
|
||||||
Content = strs
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(cmd).OnSuccess(t => {
|
|
||||||
var result = t.Result.Item2;
|
|
||||||
state.ObjectId = result["objectId"].ToString();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Compatible
|
#region Compatible
|
||||||
private readonly static Dictionary<string, string> MIMETypesDictionary;
|
|
||||||
private object mutex = new object();
|
|
||||||
private bool isExternal;
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件在 LeanCloud 的唯一Id 标识
|
/// 文件在 LeanCloud 的唯一Id 标识
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ObjectId {
|
public string ObjectId {
|
||||||
get {
|
get {
|
||||||
string str;
|
return state.ObjectId;
|
||||||
lock (mutex) {
|
|
||||||
str = state.ObjectId;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -353,204 +301,9 @@ namespace LeanCloud {
|
||||||
/// <value>
|
/// <value>
|
||||||
/// </value>
|
/// </value>
|
||||||
public bool IsExternal {
|
public bool IsExternal {
|
||||||
get {
|
get; private set;
|
||||||
return isExternal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static AVFile() {
|
|
||||||
Dictionary<string, string> strs = new Dictionary<string, string> {
|
|
||||||
{ "ai", "application/postscript" },
|
|
||||||
{ "aif", "audio/x-aiff" },
|
|
||||||
{ "aifc", "audio/x-aiff" },
|
|
||||||
{ "aiff", "audio/x-aiff" },
|
|
||||||
{ "asc", "text/plain" },
|
|
||||||
{ "atom", "application/atom+xml" },
|
|
||||||
{ "au", "audio/basic" },
|
|
||||||
{ "avi", "video/x-msvideo" },
|
|
||||||
{ "bcpio", "application/x-bcpio" },
|
|
||||||
{ "bin", "application/octet-stream" },
|
|
||||||
{ "bmp", "image/bmp" },
|
|
||||||
{ "cdf", "application/x-netcdf" },
|
|
||||||
{ "cgm", "image/cgm" },
|
|
||||||
{ "class", "application/octet-stream" },
|
|
||||||
{ "cpio", "application/x-cpio" },
|
|
||||||
{ "cpt", "application/mac-compactpro" },
|
|
||||||
{ "csh", "application/x-csh" },
|
|
||||||
{ "css", "text/css" },
|
|
||||||
{ "dcr", "application/x-director" },
|
|
||||||
{ "dif", "video/x-dv" },
|
|
||||||
{ "dir", "application/x-director" },
|
|
||||||
{ "djv", "image/vnd.djvu" },
|
|
||||||
{ "djvu", "image/vnd.djvu" },
|
|
||||||
{ "dll", "application/octet-stream" },
|
|
||||||
{ "dmg", "application/octet-stream" },
|
|
||||||
{ "dms", "application/octet-stream" },
|
|
||||||
{ "doc", "application/msword" },
|
|
||||||
{ "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" },
|
|
||||||
{ "dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template" },
|
|
||||||
{ "docm", "application/vnd.ms-word.document.macroEnabled.12" },
|
|
||||||
{ "dotm", "application/vnd.ms-word.template.macroEnabled.12" },
|
|
||||||
{ "dtd", "application/xml-dtd" },
|
|
||||||
{ "dv", "video/x-dv" },
|
|
||||||
{ "dvi", "application/x-dvi" },
|
|
||||||
{ "dxr", "application/x-director" },
|
|
||||||
{ "eps", "application/postscript" },
|
|
||||||
{ "etx", "text/x-setext" },
|
|
||||||
{ "exe", "application/octet-stream" },
|
|
||||||
{ "ez", "application/andrew-inset" },
|
|
||||||
{ "gif", "image/gif" },
|
|
||||||
{ "gram", "application/srgs" },
|
|
||||||
{ "grxml", "application/srgs+xml" },
|
|
||||||
{ "gtar", "application/x-gtar" },
|
|
||||||
{ "hdf", "application/x-hdf" },
|
|
||||||
{ "hqx", "application/mac-binhex40" },
|
|
||||||
{ "htm", "text/html" },
|
|
||||||
{ "html", "text/html" },
|
|
||||||
{ "ice", "x-conference/x-cooltalk" },
|
|
||||||
{ "ico", "image/x-icon" },
|
|
||||||
{ "ics", "text/calendar" },
|
|
||||||
{ "ief", "image/ief" },
|
|
||||||
{ "ifb", "text/calendar" },
|
|
||||||
{ "iges", "model/iges" },
|
|
||||||
{ "igs", "model/iges" },
|
|
||||||
{ "jnlp", "application/x-java-jnlp-file" },
|
|
||||||
{ "jp2", "image/jp2" },
|
|
||||||
{ "jpe", "image/jpeg" },
|
|
||||||
{ "jpeg", "image/jpeg" },
|
|
||||||
{ "jpg", "image/jpeg" },
|
|
||||||
{ "js", "application/x-javascript" },
|
|
||||||
{ "kar", "audio/midi" },
|
|
||||||
{ "latex", "application/x-latex" },
|
|
||||||
{ "lha", "application/octet-stream" },
|
|
||||||
{ "lzh", "application/octet-stream" },
|
|
||||||
{ "m3u", "audio/x-mpegurl" },
|
|
||||||
{ "m4a", "audio/mp4a-latm" },
|
|
||||||
{ "m4b", "audio/mp4a-latm" },
|
|
||||||
{ "m4p", "audio/mp4a-latm" },
|
|
||||||
{ "m4u", "video/vnd.mpegurl" },
|
|
||||||
{ "m4v", "video/x-m4v" },
|
|
||||||
{ "mac", "image/x-macpaint" },
|
|
||||||
{ "man", "application/x-troff-man" },
|
|
||||||
{ "mathml", "application/mathml+xml" },
|
|
||||||
{ "me", "application/x-troff-me" },
|
|
||||||
{ "mesh", "model/mesh" },
|
|
||||||
{ "mid", "audio/midi" },
|
|
||||||
{ "midi", "audio/midi" },
|
|
||||||
{ "mif", "application/vnd.mif" },
|
|
||||||
{ "mov", "video/quicktime" },
|
|
||||||
{ "movie", "video/x-sgi-movie" },
|
|
||||||
{ "mp2", "audio/mpeg" },
|
|
||||||
{ "mp3", "audio/mpeg" },
|
|
||||||
{ "mp4", "video/mp4" },
|
|
||||||
{ "mpe", "video/mpeg" },
|
|
||||||
{ "mpeg", "video/mpeg" },
|
|
||||||
{ "mpg", "video/mpeg" },
|
|
||||||
{ "mpga", "audio/mpeg" },
|
|
||||||
{ "ms", "application/x-troff-ms" },
|
|
||||||
{ "msh", "model/mesh" },
|
|
||||||
{ "mxu", "video/vnd.mpegurl" },
|
|
||||||
{ "nc", "application/x-netcdf" },
|
|
||||||
{ "oda", "application/oda" },
|
|
||||||
{ "ogg", "application/ogg" },
|
|
||||||
{ "pbm", "image/x-portable-bitmap" },
|
|
||||||
{ "pct", "image/pict" },
|
|
||||||
{ "pdb", "chemical/x-pdb" },
|
|
||||||
{ "pdf", "application/pdf" },
|
|
||||||
{ "pgm", "image/x-portable-graymap" },
|
|
||||||
{ "pgn", "application/x-chess-pgn" },
|
|
||||||
{ "pic", "image/pict" },
|
|
||||||
{ "pict", "image/pict" },
|
|
||||||
{ "png", "image/png" },
|
|
||||||
{ "pnm", "image/x-portable-anymap" },
|
|
||||||
{ "pnt", "image/x-macpaint" },
|
|
||||||
{ "pntg", "image/x-macpaint" },
|
|
||||||
{ "ppm", "image/x-portable-pixmap" },
|
|
||||||
{ "ppt", "application/vnd.ms-powerpoint" },
|
|
||||||
{ "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation" },
|
|
||||||
{ "potx", "application/vnd.openxmlformats-officedocument.presentationml.template" },
|
|
||||||
{ "ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow" },
|
|
||||||
{ "ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12" },
|
|
||||||
{ "pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12" },
|
|
||||||
{ "potm", "application/vnd.ms-powerpoint.template.macroEnabled.12" },
|
|
||||||
{ "ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12" },
|
|
||||||
{ "ps", "application/postscript" },
|
|
||||||
{ "qt", "video/quicktime" },
|
|
||||||
{ "qti", "image/x-quicktime" },
|
|
||||||
{ "qtif", "image/x-quicktime" },
|
|
||||||
{ "ra", "audio/x-pn-realaudio" },
|
|
||||||
{ "ram", "audio/x-pn-realaudio" },
|
|
||||||
{ "ras", "image/x-cmu-raster" },
|
|
||||||
{ "rdf", "application/rdf+xml" },
|
|
||||||
{ "rgb", "image/x-rgb" },
|
|
||||||
{ "rm", "application/vnd.rn-realmedia" },
|
|
||||||
{ "roff", "application/x-troff" },
|
|
||||||
{ "rtf", "text/rtf" },
|
|
||||||
{ "rtx", "text/richtext" },
|
|
||||||
{ "sgm", "text/sgml" },
|
|
||||||
{ "sgml", "text/sgml" },
|
|
||||||
{ "sh", "application/x-sh" },
|
|
||||||
{ "shar", "application/x-shar" },
|
|
||||||
{ "silo", "model/mesh" },
|
|
||||||
{ "sit", "application/x-stuffit" },
|
|
||||||
{ "skd", "application/x-koan" },
|
|
||||||
{ "skm", "application/x-koan" },
|
|
||||||
{ "skp", "application/x-koan" },
|
|
||||||
{ "skt", "application/x-koan" },
|
|
||||||
{ "smi", "application/smil" },
|
|
||||||
{ "smil", "application/smil" },
|
|
||||||
{ "snd", "audio/basic" },
|
|
||||||
{ "so", "application/octet-stream" },
|
|
||||||
{ "spl", "application/x-futuresplash" },
|
|
||||||
{ "src", "application/x-wais-Source" },
|
|
||||||
{ "sv4cpio", "application/x-sv4cpio" },
|
|
||||||
{ "sv4crc", "application/x-sv4crc" },
|
|
||||||
{ "svg", "image/svg+xml" },
|
|
||||||
{ "swf", "application/x-shockwave-flash" },
|
|
||||||
{ "t", "application/x-troff" },
|
|
||||||
{ "tar", "application/x-tar" },
|
|
||||||
{ "tcl", "application/x-tcl" },
|
|
||||||
{ "tex", "application/x-tex" },
|
|
||||||
{ "texi", "application/x-texinfo" },
|
|
||||||
{ "texinfo", "application/x-texinfo" },
|
|
||||||
{ "tif", "image/tiff" },
|
|
||||||
{ "tiff", "image/tiff" },
|
|
||||||
{ "tr", "application/x-troff" },
|
|
||||||
{ "tsv", "text/tab-separated-values" },
|
|
||||||
{ "txt", "text/plain" },
|
|
||||||
{ "ustar", "application/x-ustar" },
|
|
||||||
{ "vcd", "application/x-cdlink" },
|
|
||||||
{ "vrml", "model/vrml" },
|
|
||||||
{ "vxml", "application/voicexml+xml" },
|
|
||||||
{ "wav", "audio/x-wav" },
|
|
||||||
{ "wbmp", "image/vnd.wap.wbmp" },
|
|
||||||
{ "wbmxl", "application/vnd.wap.wbxml" },
|
|
||||||
{ "wml", "text/vnd.wap.wml" },
|
|
||||||
{ "wmlc", "application/vnd.wap.wmlc" },
|
|
||||||
{ "wmls", "text/vnd.wap.wmlscript" },
|
|
||||||
{ "wmlsc", "application/vnd.wap.wmlscriptc" },
|
|
||||||
{ "wrl", "model/vrml" },
|
|
||||||
{ "xbm", "image/x-xbitmap" },
|
|
||||||
{ "xht", "application/xhtml+xml" },
|
|
||||||
{ "xhtml", "application/xhtml+xml" },
|
|
||||||
{ "xls", "application/vnd.ms-excel" },
|
|
||||||
{ "xml", "application/xml" },
|
|
||||||
{ "xpm", "image/x-xpixmap" },
|
|
||||||
{ "xsl", "application/xml" },
|
|
||||||
{ "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" },
|
|
||||||
{ "xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template" },
|
|
||||||
{ "xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12" },
|
|
||||||
{ "xltm", "application/vnd.ms-excel.template.macroEnabled.12" },
|
|
||||||
{ "xlam", "application/vnd.ms-excel.addin.macroEnabled.12" },
|
|
||||||
{ "xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12" },
|
|
||||||
{ "xslt", "application/xslt+xml" },
|
|
||||||
{ "xul", "application/vnd.mozilla.xul+xml" },
|
|
||||||
{ "xwd", "image/x-xwindowdump" },
|
|
||||||
{ "xyz", "chemical/x-xyz" },
|
|
||||||
{ "zip", "application/zip" },
|
|
||||||
};
|
|
||||||
MIMETypesDictionary = strs;
|
|
||||||
}
|
|
||||||
internal static string GetMIMEType(string fileName) {
|
internal static string GetMIMEType(string fileName) {
|
||||||
try {
|
try {
|
||||||
string str = Path.GetExtension(fileName).Remove(0, 1);
|
string str = Path.GetExtension(fileName).Remove(0, 1);
|
||||||
|
|
@ -568,7 +321,7 @@ namespace LeanCloud {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>获取之后并没有实际执行下载,只是加载了文件的元信息以及物理地址(Url)
|
/// <remarks>获取之后并没有实际执行下载,只是加载了文件的元信息以及物理地址(Url)
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static Task<AVFile> GetFileWithObjectIdAsync(string objectId, CancellationToken cancellationToken) {
|
public static Task<AVFile> GetFileWithObjectIdAsync(string objectId, CancellationToken cancellationToken = default) {
|
||||||
return FileController.GetAsync(objectId, cancellationToken).OnSuccess(_ => {
|
return FileController.GetAsync(objectId, cancellationToken).OnSuccess(_ => {
|
||||||
var filestate = _.Result;
|
var filestate = _.Result;
|
||||||
return new AVFile(filestate);
|
return new AVFile(filestate);
|
||||||
|
|
@ -592,50 +345,212 @@ namespace LeanCloud {
|
||||||
};
|
};
|
||||||
return CreateWithState(fileState);
|
return CreateWithState(fileState);
|
||||||
}
|
}
|
||||||
/// <summary>
|
|
||||||
/// 根据 ObjectId 获取文件
|
internal void MergeFromJSON(IDictionary<string, object> data) {
|
||||||
/// </summary>
|
state = FileState.NewFromDict(data);
|
||||||
/// <remarks>获取之后并没有实际执行下载,只是加载了文件的元信息以及物理地址(Url)
|
|
||||||
/// </remarks>
|
|
||||||
public static Task<AVFile> GetFileWithObjectIdAsync(string objectId) {
|
|
||||||
return GetFileWithObjectIdAsync(objectId, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void MergeFromJSON(IDictionary<string, object> jsonData) {
|
|
||||||
lock (mutex) {
|
|
||||||
state.ObjectId = jsonData["objectId"] as string;
|
|
||||||
state.Url = new Uri(jsonData["url"] as string, UriKind.Absolute);
|
|
||||||
if (jsonData.ContainsKey("name")) {
|
|
||||||
state.Name = jsonData["name"] as string;
|
|
||||||
}
|
|
||||||
if (jsonData.ContainsKey("metaData")) {
|
|
||||||
state.MetaData = jsonData["metaData"] as Dictionary<string, object>;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除文件
|
/// 删除文件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task</returns>
|
/// <returns>Task</returns>
|
||||||
public Task DeleteAsync() {
|
public Task DeleteAsync(CancellationToken cancellationToken = default) {
|
||||||
return DeleteAsync(CancellationToken.None);
|
|
||||||
}
|
|
||||||
internal Task DeleteAsync(CancellationToken cancellationToken) {
|
|
||||||
return taskQueue.Enqueue(toAwait => DeleteAsync(toAwait, cancellationToken),
|
|
||||||
cancellationToken);
|
|
||||||
|
|
||||||
}
|
|
||||||
internal Task DeleteAsync(Task toAwait, CancellationToken cancellationToken) {
|
|
||||||
if (ObjectId == null) {
|
if (ObjectId == null) {
|
||||||
return Task.FromResult(0);
|
return Task.FromException(new ArgumentNullException(nameof(ObjectId)));
|
||||||
}
|
}
|
||||||
|
return FileController.DeleteAsync(state, cancellationToken);
|
||||||
return toAwait.OnSuccess(_ => {
|
|
||||||
return FileController.DeleteAsync(state, cancellationToken);
|
|
||||||
}).Unwrap().OnSuccess(_ => { });
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private readonly static Dictionary<string, string> MIMETypesDictionary = new Dictionary<string, string> {
|
||||||
|
{ "ai", "application/postscript" },
|
||||||
|
{ "aif", "audio/x-aiff" },
|
||||||
|
{ "aifc", "audio/x-aiff" },
|
||||||
|
{ "aiff", "audio/x-aiff" },
|
||||||
|
{ "asc", "text/plain" },
|
||||||
|
{ "atom", "application/atom+xml" },
|
||||||
|
{ "au", "audio/basic" },
|
||||||
|
{ "avi", "video/x-msvideo" },
|
||||||
|
{ "bcpio", "application/x-bcpio" },
|
||||||
|
{ "bin", "application/octet-stream" },
|
||||||
|
{ "bmp", "image/bmp" },
|
||||||
|
{ "cdf", "application/x-netcdf" },
|
||||||
|
{ "cgm", "image/cgm" },
|
||||||
|
{ "class", "application/octet-stream" },
|
||||||
|
{ "cpio", "application/x-cpio" },
|
||||||
|
{ "cpt", "application/mac-compactpro" },
|
||||||
|
{ "csh", "application/x-csh" },
|
||||||
|
{ "css", "text/css" },
|
||||||
|
{ "dcr", "application/x-director" },
|
||||||
|
{ "dif", "video/x-dv" },
|
||||||
|
{ "dir", "application/x-director" },
|
||||||
|
{ "djv", "image/vnd.djvu" },
|
||||||
|
{ "djvu", "image/vnd.djvu" },
|
||||||
|
{ "dll", "application/octet-stream" },
|
||||||
|
{ "dmg", "application/octet-stream" },
|
||||||
|
{ "dms", "application/octet-stream" },
|
||||||
|
{ "doc", "application/msword" },
|
||||||
|
{ "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" },
|
||||||
|
{ "dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template" },
|
||||||
|
{ "docm", "application/vnd.ms-word.document.macroEnabled.12" },
|
||||||
|
{ "dotm", "application/vnd.ms-word.template.macroEnabled.12" },
|
||||||
|
{ "dtd", "application/xml-dtd" },
|
||||||
|
{ "dv", "video/x-dv" },
|
||||||
|
{ "dvi", "application/x-dvi" },
|
||||||
|
{ "dxr", "application/x-director" },
|
||||||
|
{ "eps", "application/postscript" },
|
||||||
|
{ "etx", "text/x-setext" },
|
||||||
|
{ "exe", "application/octet-stream" },
|
||||||
|
{ "ez", "application/andrew-inset" },
|
||||||
|
{ "gif", "image/gif" },
|
||||||
|
{ "gram", "application/srgs" },
|
||||||
|
{ "grxml", "application/srgs+xml" },
|
||||||
|
{ "gtar", "application/x-gtar" },
|
||||||
|
{ "hdf", "application/x-hdf" },
|
||||||
|
{ "hqx", "application/mac-binhex40" },
|
||||||
|
{ "htm", "text/html" },
|
||||||
|
{ "html", "text/html" },
|
||||||
|
{ "ice", "x-conference/x-cooltalk" },
|
||||||
|
{ "ico", "image/x-icon" },
|
||||||
|
{ "ics", "text/calendar" },
|
||||||
|
{ "ief", "image/ief" },
|
||||||
|
{ "ifb", "text/calendar" },
|
||||||
|
{ "iges", "model/iges" },
|
||||||
|
{ "igs", "model/iges" },
|
||||||
|
{ "jnlp", "application/x-java-jnlp-file" },
|
||||||
|
{ "jp2", "image/jp2" },
|
||||||
|
{ "jpe", "image/jpeg" },
|
||||||
|
{ "jpeg", "image/jpeg" },
|
||||||
|
{ "jpg", "image/jpeg" },
|
||||||
|
{ "js", "application/x-javascript" },
|
||||||
|
{ "kar", "audio/midi" },
|
||||||
|
{ "latex", "application/x-latex" },
|
||||||
|
{ "lha", "application/octet-stream" },
|
||||||
|
{ "lzh", "application/octet-stream" },
|
||||||
|
{ "m3u", "audio/x-mpegurl" },
|
||||||
|
{ "m4a", "audio/mp4a-latm" },
|
||||||
|
{ "m4b", "audio/mp4a-latm" },
|
||||||
|
{ "m4p", "audio/mp4a-latm" },
|
||||||
|
{ "m4u", "video/vnd.mpegurl" },
|
||||||
|
{ "m4v", "video/x-m4v" },
|
||||||
|
{ "mac", "image/x-macpaint" },
|
||||||
|
{ "man", "application/x-troff-man" },
|
||||||
|
{ "mathml", "application/mathml+xml" },
|
||||||
|
{ "me", "application/x-troff-me" },
|
||||||
|
{ "mesh", "model/mesh" },
|
||||||
|
{ "mid", "audio/midi" },
|
||||||
|
{ "midi", "audio/midi" },
|
||||||
|
{ "mif", "application/vnd.mif" },
|
||||||
|
{ "mov", "video/quicktime" },
|
||||||
|
{ "movie", "video/x-sgi-movie" },
|
||||||
|
{ "mp2", "audio/mpeg" },
|
||||||
|
{ "mp3", "audio/mpeg" },
|
||||||
|
{ "mp4", "video/mp4" },
|
||||||
|
{ "mpe", "video/mpeg" },
|
||||||
|
{ "mpeg", "video/mpeg" },
|
||||||
|
{ "mpg", "video/mpeg" },
|
||||||
|
{ "mpga", "audio/mpeg" },
|
||||||
|
{ "ms", "application/x-troff-ms" },
|
||||||
|
{ "msh", "model/mesh" },
|
||||||
|
{ "mxu", "video/vnd.mpegurl" },
|
||||||
|
{ "nc", "application/x-netcdf" },
|
||||||
|
{ "oda", "application/oda" },
|
||||||
|
{ "ogg", "application/ogg" },
|
||||||
|
{ "pbm", "image/x-portable-bitmap" },
|
||||||
|
{ "pct", "image/pict" },
|
||||||
|
{ "pdb", "chemical/x-pdb" },
|
||||||
|
{ "pdf", "application/pdf" },
|
||||||
|
{ "pgm", "image/x-portable-graymap" },
|
||||||
|
{ "pgn", "application/x-chess-pgn" },
|
||||||
|
{ "pic", "image/pict" },
|
||||||
|
{ "pict", "image/pict" },
|
||||||
|
{ "png", "image/png" },
|
||||||
|
{ "pnm", "image/x-portable-anymap" },
|
||||||
|
{ "pnt", "image/x-macpaint" },
|
||||||
|
{ "pntg", "image/x-macpaint" },
|
||||||
|
{ "ppm", "image/x-portable-pixmap" },
|
||||||
|
{ "ppt", "application/vnd.ms-powerpoint" },
|
||||||
|
{ "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation" },
|
||||||
|
{ "potx", "application/vnd.openxmlformats-officedocument.presentationml.template" },
|
||||||
|
{ "ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow" },
|
||||||
|
{ "ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12" },
|
||||||
|
{ "pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12" },
|
||||||
|
{ "potm", "application/vnd.ms-powerpoint.template.macroEnabled.12" },
|
||||||
|
{ "ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12" },
|
||||||
|
{ "ps", "application/postscript" },
|
||||||
|
{ "qt", "video/quicktime" },
|
||||||
|
{ "qti", "image/x-quicktime" },
|
||||||
|
{ "qtif", "image/x-quicktime" },
|
||||||
|
{ "ra", "audio/x-pn-realaudio" },
|
||||||
|
{ "ram", "audio/x-pn-realaudio" },
|
||||||
|
{ "ras", "image/x-cmu-raster" },
|
||||||
|
{ "rdf", "application/rdf+xml" },
|
||||||
|
{ "rgb", "image/x-rgb" },
|
||||||
|
{ "rm", "application/vnd.rn-realmedia" },
|
||||||
|
{ "roff", "application/x-troff" },
|
||||||
|
{ "rtf", "text/rtf" },
|
||||||
|
{ "rtx", "text/richtext" },
|
||||||
|
{ "sgm", "text/sgml" },
|
||||||
|
{ "sgml", "text/sgml" },
|
||||||
|
{ "sh", "application/x-sh" },
|
||||||
|
{ "shar", "application/x-shar" },
|
||||||
|
{ "silo", "model/mesh" },
|
||||||
|
{ "sit", "application/x-stuffit" },
|
||||||
|
{ "skd", "application/x-koan" },
|
||||||
|
{ "skm", "application/x-koan" },
|
||||||
|
{ "skp", "application/x-koan" },
|
||||||
|
{ "skt", "application/x-koan" },
|
||||||
|
{ "smi", "application/smil" },
|
||||||
|
{ "smil", "application/smil" },
|
||||||
|
{ "snd", "audio/basic" },
|
||||||
|
{ "so", "application/octet-stream" },
|
||||||
|
{ "spl", "application/x-futuresplash" },
|
||||||
|
{ "src", "application/x-wais-Source" },
|
||||||
|
{ "sv4cpio", "application/x-sv4cpio" },
|
||||||
|
{ "sv4crc", "application/x-sv4crc" },
|
||||||
|
{ "svg", "image/svg+xml" },
|
||||||
|
{ "swf", "application/x-shockwave-flash" },
|
||||||
|
{ "t", "application/x-troff" },
|
||||||
|
{ "tar", "application/x-tar" },
|
||||||
|
{ "tcl", "application/x-tcl" },
|
||||||
|
{ "tex", "application/x-tex" },
|
||||||
|
{ "texi", "application/x-texinfo" },
|
||||||
|
{ "texinfo", "application/x-texinfo" },
|
||||||
|
{ "tif", "image/tiff" },
|
||||||
|
{ "tiff", "image/tiff" },
|
||||||
|
{ "tr", "application/x-troff" },
|
||||||
|
{ "tsv", "text/tab-separated-values" },
|
||||||
|
{ "txt", "text/plain" },
|
||||||
|
{ "ustar", "application/x-ustar" },
|
||||||
|
{ "vcd", "application/x-cdlink" },
|
||||||
|
{ "vrml", "model/vrml" },
|
||||||
|
{ "vxml", "application/voicexml+xml" },
|
||||||
|
{ "wav", "audio/x-wav" },
|
||||||
|
{ "wbmp", "image/vnd.wap.wbmp" },
|
||||||
|
{ "wbmxl", "application/vnd.wap.wbxml" },
|
||||||
|
{ "wml", "text/vnd.wap.wml" },
|
||||||
|
{ "wmlc", "application/vnd.wap.wmlc" },
|
||||||
|
{ "wmls", "text/vnd.wap.wmlscript" },
|
||||||
|
{ "wmlsc", "application/vnd.wap.wmlscriptc" },
|
||||||
|
{ "wrl", "model/vrml" },
|
||||||
|
{ "xbm", "image/x-xbitmap" },
|
||||||
|
{ "xht", "application/xhtml+xml" },
|
||||||
|
{ "xhtml", "application/xhtml+xml" },
|
||||||
|
{ "xls", "application/vnd.ms-excel" },
|
||||||
|
{ "xml", "application/xml" },
|
||||||
|
{ "xpm", "image/x-xpixmap" },
|
||||||
|
{ "xsl", "application/xml" },
|
||||||
|
{ "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" },
|
||||||
|
{ "xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template" },
|
||||||
|
{ "xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12" },
|
||||||
|
{ "xltm", "application/vnd.ms-excel.template.macroEnabled.12" },
|
||||||
|
{ "xlam", "application/vnd.ms-excel.addin.macroEnabled.12" },
|
||||||
|
{ "xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12" },
|
||||||
|
{ "xslt", "application/xslt+xml" },
|
||||||
|
{ "xul", "application/vnd.mozilla.xul+xml" },
|
||||||
|
{ "xwd", "image/x-xwindowdump" },
|
||||||
|
{ "xyz", "chemical/x-xyz" },
|
||||||
|
{ "zip", "application/zip" }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue