如何使用 MongoDB GridFS 和 AngularJs 在 dotnet 核心中创建 CDN 服务器 [英] How to create a CDN server in dotnet core using MongoDB GridFS and AngularJs
问题描述
我们想使用 MongoDB GridFS 和 angular js 在 .net core 中创建一个名为 CDN 的解耦文件服务器.
从各种来源我尽力解决这个问题.最后我们做到了.
我使用了 Visual Studio 2017 和 .NETCore 1.1为此,我遵循以下几点:1. 在 MongoDB GridFS 中编写代码创建一个像
这样的界面公共接口 IGridFsRepository : IDisposable{任务<字符串>UploadAsync(IFormFile 文件);任务AnyAsync(ObjectId id);任务AnyAsync(字符串文件名);任务 DeleteAsync(string fileName);任务 DeleteAsync(ObjectId id);任务<GridFSDownloadStream<ObjectId>>下载异步(字符串文件名);任务<GridFSDownloadStream<ObjectId>>DownloadAsync(ObjectId id);object GetAllFilesByContentType(string contentType, int skip, int拿);object GetAllFiles(int skip, int take);}
然后创建 MongoDbCdnContext:
公共抽象类 MongoDbCdnContext{公共 IGridFSBucket GridFsBucket {get;}受保护的 MongoDbCdnContext(string connectionStringName){var config = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").建造();变量连接字符串 =config.GetConnectionString(connectionStringName);var connection = new MongoUrl(connectionString);var settings = MongoClientSettings.FromUrl(connection);//#如果调试//settings.ClusterConfigurator = builder =>builder.Subscribe(started =>//{//Debug.Write(started.Command);//});//#万一var client = new MongoClient(settings);var database = client.GetDatabase(connection.DatabaseName);GridFsBucket = 新的 GridFSBucket(数据库);}}
然后实现它:
公共类 GridFsRepository : MongoDbCdnContext,IGridFsRepository{公共 GridFsRepository() : base("MongoCdn"){}公共异步任务上传异步(IFormFile 文件){var 选项 = 新的 GridFSUploadOptions{元数据 = new BsonDocument("contentType", file.ContentType)};使用 (var reader = newStreamReader((Stream)file.OpenReadStream())){var stream = reader.BaseStream;var fileId = 等待GridFsBucket.UploadFromStreamAsync(file.FileName, stream,选项);返回 fileId.ToString();}}公共异步任务AnyAsync(ObjectId id){var filter = Builders.Filter.Eq("_id", id);返回等待 GridFsBucket.Find(filter).AnyAsync();}公共任务AnyAsync(字符串文件名){var filter = Builders.Filter.Where(x =>x.文件名 == 文件名);返回 GridFsBucket.Find(filter).AnyAsync();}公共异步任务 DeleteAsync(字符串文件名){var fileInfo = await GetFileInfoAsync(fileName);如果(文件信息!= null)等待 DeleteAsync(fileInfo.Id);}公共异步任务 DeleteAsync(ObjectId id){等待 GridFsBucket.DeleteAsync(id);}私有异步任务GetFileInfoAsync(字符串文件名){var filter = Builders.Filter.Eq(x => x.Filename,文档名称);var 文件信息 = 等待GridFsBucket.Find(filter).FirstOrDefaultAsync();返回文件信息;}公共异步任务>DownloadAsync(ObjectId id){返回等待 GridFsBucket.OpenDownloadStreamAsync(id);}公共异步任务>下载异步(字符串文件名){返回等待GridFsBucket.OpenDownloadStreamByNameAsync(fileName);}公共 IEnumerableGetAllFilesByContentType(字符串contentType, int skip, int take){var filter = Builders.Filter.Eq(info => info.Metadata, new BsonDocument(newBsonElement("contentType", contentType)));var 选项 = 新的 GridFSFindOptions{限制 = 采取,跳过 = 跳过,};var stream = GridFsBucket.Find(过滤器,选项).ToList().Select(s => new GridFSFileInfoDto{Id = s.Id,文件名 = s.文件名,元数据 = s.元数据,长度 = s.Length + "",UploadDateTime = s.UploadDateTime,}).ToList();返回流;}公共 IEnumerableGetAllFiles(int skip, int take){var 选项 = 新的 GridFSFindOptions{限制 = 采取,跳过 = 跳过,};var stream = GridFsBucket.Find(newBsonDocumentFilterDefinition>(新BsonDocument()), 选项).ToList().Select(s => new GridFSFileInfoDto{Id = s.Id,文件名 = s.文件名,元数据 = s.元数据,长度 = s.Length + "",UploadDateTime = s.UploadDateTime,}).ToList();返回流;}公共无效处置(){GC.SuppressFinalize(this);}}
然后在.netcore web api中创建一个控制器
[EnableCors("AllowAll")][验证模型][路由(api/文件")]公共类 FileController :控制器{私有只读 IGridFsRepository _gridFsManager;公共文件控制器(IGridFsRepository gridFsRepository){_gridFsManager = gridFsRepository;}[允许匿名][HttpGet("{fileName}",Name = "GetByFileName")]公共异步任务GetByFileName(字符串文件名){返回 Ok(await _gridFsManager.DownloadAsync(fileName));}[允许匿名][HttpGet("{id}",Name = "GetById")]公共异步任务GetByFileName(ObjectId id){返回 Ok(await _gridFsManager.DownloadAsync(id));}[HttpPost]公共异步任务上传([FromForm] IFormFile 文件){如果(文件!= null){if (file.ContentType.Contains("image"))return BadRequest("抱歉,只有图片 jpg/jpeg/png公认");if (file.Length >= (300 * 1024))return BadRequest($"Sorry {file.FileName} 超出了300kb");等待 _gridFsManager.DeleteAsync(file.FileName);等待 _gridFsManager.UploadAsync(file);}返回 NoContent();}[HttpDelete]公共异步任务删除(字符串ID){等待 _gridFsManager.DeleteAsync(id);返回 NoContent();}}
请不要忘记解决依赖:
services.AddScoped();
从 html 到文件:
<span>标志</span><input type="file" data-ng-model="cp.data.file"id="selectedFile" name="selectedFile">
让我们进入 UI 层:首先创建一个角度工厂:
(函数(){严格使用";angular.module("appCdn", []).factory('fileUploader', ["$http", function ($http) {返回 {上传:函数(url,文件,fileMaxSize,fileName,回调){如果(this.isValidFileSize(fileMaxSize,文件)){var fd = new FormData();//创建FormData对象如果(文件名)fd.append("文件", 文件, 文件名);别的fd.append("文件", 文件);$http.post(url, fd, {变换请求:angular.identity,标头:{'内容类型':未定义}}).成功(功能(数据){打回来();}).错误(函数(数据){Materialize.toast("Sorry! error in file upload", 4000, 'red');});} 别的 {Materialize.toast("Sorry!" + file.name + " 超过 300kb", 4000, 'red');}},isValidFileSize: 函数 (maximumAllowedSize, 文件) {if (file.size >= maximumAllowedSize) {返回假;} 别的 {返回真;}}};}]);})();
然后创建一个角度控制器:
angular.module('ecom').controller('companyProfileCtrl',['$http', 'config', "confirmation", "fileUploader",companyProfile]);函数 companyProfile($http,配置,确认,fileUploader){var vm = 这个;vm.getProfile = 函数 () {$http.get(config.apiUrl + "companyProfile").成功(功能(响应){vm.data = 响应;});};vm.save = 函数(配置文件){确认.确认(功能(){$http.post(config.apiUrl + "companyProfile", 个人资料).成功(功能(数据){var 文件名 = "";如果(profile.id){文件名 = profile.id;} 别的 {文件名 = 数据;}vm.upload(文件名,功能 () {Materialize.toast("succeeded", 4000, 'green');window.location.href = window.history.back();});}).错误(功能(数据){Materialize.toast(data, 4000, 'red');});});};vm.upload = 函数(文件名,回调){var photo = document.getElementById("selectedFile");var file = photo.files[0];if (file) {fileUploader.upload(config.cdnUrl + "files",//300kb文件,1024 * 300,文件名,回调);}};};
最后以html显示图像:
我们终于做到了.这就是全部.我总是期待着接受批评.
We want to create a decoupled file server named CDN in .net core using MongoDB GridFS and angular js.
From various sources I tried my best to solve the issue. And finally we done this.
I used Visual Studio 2017 and .NETCore 1.1 To do so I follow the followings: 1. Write Code in MongoDB GridFS create an interface like
public interface IGridFsRepository : IDisposable
{
Task<string> UploadAsync(IFormFile file);
Task<bool> AnyAsync(ObjectId id);
Task<bool> AnyAsync(string fileName);
Task DeleteAsync(string fileName);
Task DeleteAsync(ObjectId id);
Task<GridFSDownloadStream<ObjectId>> DownloadAsync(string fileName);
Task<GridFSDownloadStream<ObjectId>> DownloadAsync(ObjectId id);
object GetAllFilesByContentType(string contentType, int skip, int
take);
object GetAllFiles(int skip, int take);
}
then create MongoDbCdnContext:
public abstract class MongoDbCdnContext
{
public IGridFSBucket GridFsBucket {get;}
protected MongoDbCdnContext(string connectionStringName)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var connectionString =
config.GetConnectionString(connectionStringName);
var connection = new MongoUrl(connectionString);
var settings = MongoClientSettings.FromUrl(connection);
//#if DEBUG
// settings.ClusterConfigurator = builder =>
builder.Subscribe<CommandStartedEvent>(started =>
// {
// Debug.Write(started.Command);
// });
//#endif
var client = new MongoClient(settings);
var database = client.GetDatabase(connection.DatabaseName);
GridFsBucket = new GridFSBucket(database);
}
}
then implement it:
public class GridFsRepository : MongoDbCdnContext,
IGridFsRepository
{
public GridFsRepository() : base("MongoCdn")
{
}
public async Task<string> UploadAsync(IFormFile file)
{
var options = new GridFSUploadOptions
{
Metadata = new BsonDocument("contentType", file.ContentType)
};
using (var reader = new
StreamReader((Stream)file.OpenReadStream()))
{
var stream = reader.BaseStream;
var fileId = await
GridFsBucket.UploadFromStreamAsync(file.FileName, stream,
options);
return fileId.ToString();
}
}
public async Task<bool> AnyAsync(ObjectId id)
{
var filter = Builders<GridFSFileInfo>.Filter.Eq("_id", id);
return await GridFsBucket.Find(filter).AnyAsync();
}
public Task<bool> AnyAsync(string fileName)
{
var filter = Builders<GridFSFileInfo>.Filter.Where(x =>
x.Filename == fileName);
return GridFsBucket.Find(filter).AnyAsync();
}
public async Task DeleteAsync(string fileName)
{
var fileInfo = await GetFileInfoAsync(fileName);
if (fileInfo != null)
await DeleteAsync(fileInfo.Id);
}
public async Task DeleteAsync(ObjectId id)
{
await GridFsBucket.DeleteAsync(id);
}
private async Task<GridFSFileInfo> GetFileInfoAsync(string fileName)
{
var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename,
fileName);
var fileInfo = await
GridFsBucket.Find(filter).FirstOrDefaultAsync();
return fileInfo;
}
public async Task<GridFSDownloadStream<ObjectId>>
DownloadAsync(ObjectId id)
{
return await GridFsBucket.OpenDownloadStreamAsync(id);
}
public async Task<GridFSDownloadStream<ObjectId>>
DownloadAsync(string fileName)
{
return await
GridFsBucket.OpenDownloadStreamByNameAsync(fileName);
}
public IEnumerable<GridFSFileInfoDto> GetAllFilesByContentType(string
contentType, int skip, int take)
{
var filter = Builders<GridFSFileInfo>.Filter
.Eq(info => info.Metadata, new BsonDocument(new
BsonElement("contentType", contentType)));
var options = new GridFSFindOptions
{
Limit = take,
Skip = skip,
};
var stream = GridFsBucket.Find(filter, options)
.ToList()
.Select(s => new GridFSFileInfoDto
{
Id = s.Id,
Filename = s.Filename,
MetaData = s.Metadata,
Length = s.Length + "",
UploadDateTime = s.UploadDateTime,
})
.ToList();
return stream;
}
public IEnumerable<GridFSFileInfoDto> GetAllFiles(int skip, int take)
{
var options = new GridFSFindOptions
{
Limit = take,
Skip = skip,
};
var stream = GridFsBucket.Find(new
BsonDocumentFilterDefinition<GridFSFileInfo<ObjectId>>(new
BsonDocument()), options)
.ToList()
.Select(s => new GridFSFileInfoDto
{
Id = s.Id,
Filename = s.Filename,
MetaData = s.Metadata,
Length = s.Length + "",
UploadDateTime = s.UploadDateTime,
})
.ToList();
return stream;
}
public void Dispose()
{
GC.SuppressFinalize(this);
}
}
then create a controller in .netcore web api
[EnableCors("AllowAll")]
[ValidateModel]
[Route("api/files")]
public class FileController : Controller
{
private readonly IGridFsRepository _gridFsManager;
public FileController(IGridFsRepository gridFsRepository)
{
_gridFsManager = gridFsRepository;
}
[AllowAnonymous]
[HttpGet("{fileName}",Name = "GetByFileName")]
public async Task<IActionResult> GetByFileName(string fileName)
{
return Ok(await _gridFsManager.DownloadAsync(fileName));
}
[AllowAnonymous]
[HttpGet("{id}",Name = "GetById")]
public async Task<IActionResult> GetByFileName(ObjectId id)
{
return Ok(await _gridFsManager.DownloadAsync(id));
}
[HttpPost]
public async Task<IActionResult> Upload([FromForm] IFormFile file)
{
if (file != null)
{
if (file.ContentType.Contains("image"))
return BadRequest("Sorry only image jpg/jpeg/png
accepted");
if (file.Length >= (300 * 1024))
return BadRequest($"Sorry {file.FileName} is exceeds
300kb");
await _gridFsManager.DeleteAsync(file.FileName);
await _gridFsManager.UploadAsync(file);
}
return NoContent();
}
[HttpDelete]
public async Task<IActionResult> Delete(string id)
{
await _gridFsManager.DeleteAsync(id);
return NoContent();
}
}
please do not forget to resolve dependency:
services.AddScoped<IGridFsRepository, GridFsRepository>();
to file from html:
<div class="btn">
<span>Logo</span>
<input type="file" data-ng-model="cp.data.file"
id="selectedFile" name="selectedFile">
</div>
lets go to UI layer: first create an angular factory:
(function () {
"use strict";
angular.module("appCdn", [])
.factory('fileUploader', ["$http", function ($http) {
return {
upload: function (url, file, fileMaxSize, fileName, callback) {
if (this.isValidFileSize(fileMaxSize, file)) {
var fd = new FormData(); //Create FormData object
if (fileName)
fd.append("file", file, fileName);
else
fd.append("file", file);
$http.post(url, fd, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}).success(function (data) {
callback();
}).error(function (data) {
Materialize.toast("Sorry! error in file upload", 4000, 'red');
});
} else {
Materialize.toast("Sorry! " + file.name + " exceeds 300kb", 4000, 'red');
}
},
isValidFileSize: function (maximumAllowedSize, file) {
if (file.size >= maximumAllowedSize) {
return false;
} else {
return true;
}
}
};
}
]);
})();
after that create an angular controller:
angular.module('ecom').controller('companyProfileCtrl',
['$http', 'config', "confirmation", "fileUploader",companyProfile]);
function companyProfile($http, config, confirmation, fileUploader) {
var vm = this; vm.getProfile = function () {
$http.get(config.apiUrl + "companyProfile")
.success(function (response) {
vm.data = response;
});
};
vm.save = function (profile) {
confirmation.confirm(function () {
$http.post(config.apiUrl + "companyProfile", profile)
.success(function (data) {
var fileName = "";
if (profile.id) {
fileName = profile.id;
} else {
fileName = data;
}
vm.upload(fileName,
function () {
Materialize.toast("succeeded", 4000, 'green');
window.location.href = window.history.back();
});
})
.error(function (data) {
Materialize.toast(data, 4000, 'red');
});
});
};
vm.upload = function (fileName, callback) {
var photo = document.getElementById("selectedFile");
var file = photo.files[0];
if (file) {fileUploader.upload(config.cdnUrl + "files",
//300kb
file, 1024 * 300, fileName, callback);
}
};
};
finally to show the image in html:
<div><img src="http://localhost:41792/api/files/{{cp.data.id}}"
class="img-responsive visible-md visible-lg img-margin-desktop"
width="350" height="167" />
</div>
finally we done this. this is all. I always looking forward to receiving criticism.
这篇关于如何使用 MongoDB GridFS 和 AngularJs 在 dotnet 核心中创建 CDN 服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!