原理是获取图片的二进制byte[],转成MemoryStream流,加入到响应头header和响应体Body中供前端访问下载
Controller.cs 文件
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;
using BaseService.Common;
using BaseService.Domain.Shared.Common;
using Tzkj.AspNetCore.ActionResults;
using Tzkj.Core.Constants;
using Tzkj.Core.Enums;
using Volo.Abp;
using BaseService.Controllers;
using System.Net;
using Tzkj.Superhard.Domain.Shared.Volo.Abp.Users;
namespace BaseService.HttpApi.Common;
[Area("base")]
[Route("api/base/storage")]
public class StorageController : BaseServiceController
{
private readonly IStorageAppService _storageAppService;
public StorageController(IStorageAppService storageAppService)
{
_storageAppService = storageAppService;
}
///
/// 上传文件
///
/// RoleCert:角色认证资料;Promotion:宣传视频;Page:cms文章
/// 1:doc/docx/pdf;2:图片".png", ".jpg", ".jpeg";3:视频 ".mp4", ".avi", ".wmv";4:压缩包 .rar
/// 上传文件
///
///
[HttpPost("upload")]
[RequestFormLimits(MultipartBodyLengthLimit = BlobStoringConstants.Upload.MultipartBodyLengthLimit)]
[RequestSizeLimit(BlobStoringConstants.Upload.MaxRequestBodySize)]
public async Task UpdateAsync([FromForm]string contentType,[FromForm] AllowUploadFileType fileType, IFormFile file)
{
var storageContentType = StorageContentType.FromValue(contentType);
if((int)fileType==0)
throw new UserFriendlyException("请提供要上传的文件类型!");
using var memoryStream = new MemoryStream();
await file.CopyToAsync(memoryStream);
return await _storageAppService.UploadAsync(file.FileName,memoryStream,storageContentType,fileType);
}
[HttpPost("download")]
public async Task DownloadAsync(string storageName)
{
var bytes = await _storageAppService.DownloadAsync(storageName);
var fileName = Path.GetFileName(storageName);
return new MultiFileResult(bytes, fileName);
}
///
/// 下载会员证书(这样也可以)
///
///
///
[HttpGet("download-memberCard")]
public async Task DownloadMeberCardAsync(Guid id)
{
var bytes = await _companyInfoService.GetMemberCardUrlAsync(id);
//var fileName = Path.GetFileName(storageName);
var fileName = "memberCard.jpeg";
return new MultiFileResult(bytes, fileName);
}
[HttpDelete]
public async Task DeleteAsync(string storageName)
{
await _storageAppService.DeleteAsync(storageName);
}
[HttpGet]
public Task GetStorageFullUrl(string storageName)
{
return Task.FromResult(_storageAppService.GetMinioStorageFullUrl(storageName));
}
}
还有中情况pemkey类型的文件可以直接File打开二进制下载
///
/// 获取授权请求文件
///
///
[HttpGet("/auth-apply-file")]
public IActionResult DownloadAuthRequestFileAsync(string versionId,string appId)
{
byte[] data = _sdkACLService.GetAuthApplyInfo(versionId,appId);
var contentDisposition = new System.Net.Mime.ContentDisposition
{
FileName = "AuthApplyInfo.pemkey"
};
Response.Headers.Add("Content-Disposition", contentDisposition.ToString());
return File(data, "text/plain");
}
StorageAppService.cs文件
using System;
using System.Collections.Generic;
using BaseService.Domain.Shared.Common;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Tzkj.BlobStorings;
using Tzkj.BlobStorings.Abstractions;
using Tzkj.Core.Constants;
using Tzkj.Core.Enums;
using Volo.Abp.Application.Services;
using Volo.Abp.BlobStoring;
using Volo.Abp.Validation;
using Volo.Abp;
namespace BaseService.Common;
[RemoteService(IsEnabled = false)]
public class StorageAppService : ApplicationService, IStorageAppService
{
private readonly IBlobContainer _blobContainer;
private readonly MinioOptions _minioOptions;
public StorageAppService(IOptions options, IBlobContainer blobContainer)
{
_blobContainer = blobContainer;
_minioOptions = options.Value;
}
[DisableValidation]
public async Task UploadAsync(string physicalFileName, Stream fileStream, StorageContentType contentType, AllowUploadFileType allowUploadFileType)
{
FileUploadHelper.VerifyStreamedFile(physicalFileName, fileStream,allowUploadFileType, BlobStoringConstants.Upload.MultipartBodyLengthLimit);
var fileExt = Path.GetExtension(physicalFileName);
var relativeUri = FileUploadHelper.GetRelativeUri(new List{contentType.Value,allowUploadFileType.ToString()}, $"{Path.GetFileNameWithoutExtension(physicalFileName)}_{GuidGenerator.Create()}", fileExt);
await _blobContainer.SaveAsync(relativeUri, fileStream, true);
var fullUri = GetMinioStorageFullUrl(relativeUri);
return fullUri;
}
public Task DownloadAsync(string storageName)
{
return _blobContainer.GetAllBytesOrNullAsync(storageName);
}
public Task DeleteAsync(string storageName)
{
return _blobContainer.DeleteAsync(storageName);
}
///
/// 获取存储对象访问地址
///
///
///
public string GetMinioStorageFullUrl(string storageName)
{
storageName = storageName.TrimStart('/');
var endpoint = _minioOptions.OutSideEndpoint.Split(':');
var host = endpoint[0];
var port = endpoint.Length > 1 ? endpoint[1] : "80";
var builder = new UriBuilder("http", host,Convert.ToInt32(port));
var paths=new List { _minioOptions.BucketName,"host",storageName};
builder.Path = Path.Combine(paths.ToArray());
return builder.ToString();
}
}
MultiFileResult.cs文件
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Volo.Abp;
using Volo.Abp.Http;
namespace Tzkj.AspNetCore.ActionResults;
public class MultiFileResult : ActionResult
{
private readonly byte[] _fileBytes;
private readonly string _fileNameWithExt;
public MultiFileResult(byte[] fileBytes, string fileNameWithExt)
{
_fileBytes = fileBytes;
_fileNameWithExt = fileNameWithExt;
}
public override async Task ExecuteResultAsync(ActionContext context)
{
context.HttpContext.Response.ContentType = GetMimeType(_fileNameWithExt);
using var stream = new MemoryStream(_fileBytes);
context.HttpContext.Response.Headers.Add("Content-Disposition", (StringValues)new string[1]
{
"attachment; filename=" + WebUtility.UrlEncode(_fileNameWithExt)
});
await stream.CopyToAsync(context.HttpContext.Response.Body);
}
private string GetMimeType(string fileNameWithExt)
{
var extName = Path.GetExtension(fileNameWithExt).ToLowerInvariant();
if (string.IsNullOrWhiteSpace(extName))
throw new UserFriendlyException("缺少文件扩展名,未知文件类型");
else if (extName.Equals(".doc"))
return "application/msword";
else if (extName.Equals(".docx"))
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
else if (extName.Equals(".pdf"))
return MimeTypes.Application.Pdf;
else if (extName.Equals(".rar") ||
extName.Equals(".pkl"))
return "application/octet-stream";
else if (extName.Equals(".jpeg"))
return MimeTypes.Image.Jpeg;
throw new BusinessException("不支持的文件扩展名");
}
}