I really like aspnetboilerplate framework, I learning/using it now..
How do you do \'File Upload\' logic/method in AppServices for aspnetboilerplate? The angular par
There is no way to upload a file from Appservice you need to create a web Api controler with a particular method for this action.
public class EntityImageController : AbpApiController
{
private IEntityImageAppService iEntityAppService;
public EntityImageController( IEntityImageAppService pEntityImgAppService ) : base()
{
this.LocalizationSourceName = AppConsts.LocalizationSourceName;
this.iEntityImgAppService = pEntityImgAppService;
}
[AbpAuthorize( PermissionNames.Entity_Update )]
[HttpPost]
public async Task<HttpResponseMessage> Set()
{
// Check if the request contains multipart/form-data.
if( !Request.Content.IsMimeMultipartContent() )
{
throw new HttpResponseException( HttpStatusCode.UnsupportedMediaType );
}
string root = HttpContext.Current.Server.MapPath( "~/App_Data" );
var provider = new MultipartFormDataStreamProvider( root );
try
{
// Read the form data.
await Request.Content.ReadAsMultipartAsync( provider );
var mEntityId = provider.FormData[ "EntityId" ];
MultipartFileData mFileData = provider.FileData.FirstOrDefault();
var mFileInfo = new FileInfo( mFileData.LocalFileName );
var mImageBytes = File.ReadAllBytes( mFileInfo.FullName );
await this.iEntityImgAppService.Set( new EntityImageInput
{
ImageInfo = mImageBytes,
EntityId = Convert.ToInt32( mEntityId )
} );
return Request.CreateResponse( HttpStatusCode.OK );
}
catch( System.Exception e )
{
return Request.CreateErrorResponse( HttpStatusCode.InternalServerError, e );
}
}
}
Create a file upload controller in the web.core project. Then reference your appService to process the file.
[HttpPost]
[AbpMvcAuthorize(PermissionNames.TenantPageJob)]
public async Task UploadExcelJobs()
{
var files = Request.Form.Files;
foreach (var file in files)
{
if (file.Length > 0 && file.ContentType.Contains("excel"))
{
var targetPath = Path.Combine(Path.GetTempPath(), (new Guid().ToString()), file.FileName);
var fs = new FileStream(targetPath, FileMode.OpenOrCreate);
await file.CopyToAsync(fs);
await _myAppService.ProcessFile(targetPath);
System.IO.File.Delete(targetPath);
}
}
}
All application services have access to the HttpContext object, so they are also able to handle file upload. To upload a file to an app. service make sure to use the correct url + headers.
App. service example:
public class MyUploadService : MyApplicationBaseClass, IMyUploadService
{
/// <summary>
/// References the logging service.
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Construct an new instance of this application service.
/// </summary>
public MyUploadService(ILogger logger)
{
_logger = logger;
}
/// <summary>
/// Method used to handle HTTP posted files.
/// </summary>
public async Task Upload()
{
// Checking if files are sent to this app service.
if(HttpContext.Current.Request.Files.Count == 0)
throw new UserFriendlyException("No files given.");
// Processing each given file.
foreach(var file in HttpContext.Current.Request.Files)
{
// Reading out meta info.
var fileName = file.fileName;
var extension = Path.GetExtension(file.FileName);
// Storing file on disk.
file.SaveAs("~/uploads");
}
}
}
There is no way to do that via the ApplicationServices. You need to do that in the Web project with an MVC controller and action, like you would do it in a regular project. If you need more help, I can assist.
The point is is how to get the files from the method of the class XXXAppService which derived from ApplicationService, not from the XXXController which derived from AbpController or Microsoft.AspNetCore.Mvc.Controller.
So you should remember the class: HttpContext/HtttpRequest/HttpResponse!!!
Solution: Inject httpContextAccessor in the class XXXAppService will achive it. https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-5.0
Here is my codes, wish will help you!
------Server side (ABP)--------------
[Route("api/")]
public class XXXAppService : ApplicationService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public XXXAppService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
[HttpPost, Route("upload")]
public void UploadFile()
{
var files = _httpContextAccessor.HttpContext.Request.Form.Files;
//do logics as you like here...
}
}
---(1) UI (PrimeNG upload component)
<p-fileUpload name="demo[]" [multiple]="true" [url]="uploadUrl"
(onUpload)="onUpload($event)">
<ng-template pTemplate="content">
<ul *ngIf="uploadedFiles.length">
<li *ngFor="let file of uploadedFiles">{{file.name}} - {{file.size / 1000}}kb</li>
</ul>
</ng-template>
</p-fileUpload>
---(2) UI logic (component)
import { AppConsts } from '@shared/AppConsts';
uploadUrl: string = '';
uploadedFiles: any[] = [];
ngOnInit() {
//http://localhost:21021/api/upload
let url_ = AppConsts.remoteServiceBaseUrl + "/api/upload";
this.uploadUrl = url_.replace(/[?&]$/, "");
}
onUpload(event: any) {
_.forEach(event.files, v => {
this.uploadedFiles.push(v);
});
}
We implement file upload method : - use sql server fileTable technology - implement application method's service to accept data similar to this Dto
public FileDto File { get; set; }
...
public class FileDto
{
public FileDto()
{
}
public FileDto(string file, string fileType)
{
File = file;
FileType = fileType;
}
[DisableAuditing]
public string File { get; set; }
public string FileName { get; set; }
public Guid? StreamId { get; set; }
public string FileType { get; set; } = "";
[DisableAuditing]
public string FileWithHeader
{
get
{
if (FileType == null|| FileType=="")
return "";
if (FileType.ToLower() == "jpg" || FileType.ToLower() == "jpeg")
return "data:image/Jpeg;base64," + File;
if (FileType.ToLower() == "png")
return "data:image/png;base64," + File;
if (FileType.ToLower() == "gif")
return "data:image/gif;base64," + File;
if (FileType.ToLower() == "ppt")
return "data:application/vnd.ms-powerpoint;base64," + File;
if (FileType.ToLower() == "xls")
return "data:application/vnd.ms-excel;base64," + File;
if (FileType.ToLower() == "doc")
return "data:application/msword;base64," + File;
if (FileType.ToLower() == "zip")
return "data:application/zip;base64," + File;
if (FileType.ToLower() == "exe")
return "data:application/octet-stream;base64," + File;
if (FileType.ToLower() == "txt")
return "data:text/plain;base64," + File;
if (FileType.ToLower() == "pdf")
return "data:application/pdf;base64," + File;
if (FileType.ToLower() == "bmp")
return "data:image/bmp;base64," + File;
if (FileType.ToLower() == "csv")
return "data:text/csv;base64," + File;
if (FileType.ToLower() == "pptx")
return "data:application/vnd.openxmlformats-officedocument.presentationml.presentation;base64," + File;
if (FileType.ToLower() == "xlsx")
return "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64," + File;
if (FileType.ToLower() == "docx")
return "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64," + File;
if (FileType.ToLower() == "rar")
return "data:application/x-rar-compressed;base64," + File;
if (FileType.ToLower() == "rtf")
return "data:application/rtf;base64," + File;
return "";
}
}
}
and method implementation
public UploadFileOutput UploadFile(UploadFileInput input)
{
if (input.Id <= 0 || input.File == null)
{
throw new UserFriendlyException(L("GetDataError"));
}
return new UploadFileOutput()
{
StreamId = _attachmentRepo.InsertAttachment(input.File.FileName, Convert.FromBase64String(input.File.File), LIMSConsts.HeightThumbnail, true, ServerConfig.ThumbnailImagePath),
};
}
insertAttachment method:
public Guid InsertAttachment(string fileName, byte[] fileStream, int heightThumbnail = 50, bool saveThumbnail = false,string thumbLocationPath=null)
{
Guid AttachmentId = Guid.Empty;
SqlParameter _attachmentId = new SqlParameter();
_attachmentId.ParameterName = "@attachmentId";
_attachmentId.Direction = System.Data.ParameterDirection.InputOutput;
_attachmentId.Value = AttachmentId;
SqlParameter _fileStream = new SqlParameter();
_fileStream.SqlDbType = System.Data.SqlDbType.VarBinary;
_fileStream.Value = fileStream;
_fileStream.ParameterName = "@fileStream";
Context.Database.ExecuteSqlCommand("EXECUTE dbo.sp_AttachmentFile_Insert @AttachmentId OUTPUT,@fileName,@fileStream",
_attachmentId,
new SqlParameter("@fileName", fileName),
_fileStream);
if (saveThumbnail == true) {
var ms = new MemoryStream(fileStream);
var image = Image.FromStream(ms);
var width = (int)(heightThumbnail * image.Width / image.Height);
var height = (int)(heightThumbnail);
var Thumbnail = new Bitmap(width, height);
Graphics.FromImage(Thumbnail).DrawImage(image, 0, 0, width, height);
Bitmap Thumb= new Bitmap(Thumbnail);
Thumb.Save(Path.Combine(thumbLocationPath, _attachmentId.Value+".jpg"), ImageFormat.Jpeg);
}
return (Guid)_attachmentId.Value;
}
and Stored procedure implementation
ALTER PROC [dbo].[sp_AttachmentFile_Insert]
@AttachmentId uniqueidentifier out,
@fileName nvarchar(256),
@fileStream VARBINARY(max)
AS SET @AttachmentId=NEWID()
WHILE(EXISTS(SELECT 1 FROM dbo.Attachment WHERE name=@fileName))
BEGIN
DECLARE @fileExtention NVARCHAR(100)
SELECT @fileExtention ='.'+dbo.GetFileExtension(@fileName)
SET @fileName=REPLACE(@fileName,@fileExtention,'')+
CAST(DATEPART( DAY, GETDATE()) AS VARCHAR(10))+'_'
+CAST(DATEPART( HOUR, GETDATE()) AS VARCHAR(10))+'_'+
+CAST(DATEPART( MINUTE, GETDATE()) AS VARCHAR(10))+'_'+
+CAST(DATEPART( SECOND, GETDATE()) AS VARCHAR(10))+@fileExtention
END
INSERT into dbo.Attachment(stream_id,name,file_stream)
VALUES(@AttachmentId,@fileName,@fileStream)
and finally Thank to "Halil İbrahim Kalkan" for thihs awesome framework.