What i mean is, that its possible to use IRemoteStreamContent like in the link if you call the download /upload from an other Application Service. The logic in the link is the same as always. Thelogic and operations are done at application level, not apicontroller level. ( also the download method return a mvc FileStreamResult not a io stream - Casting would cause additional memory use. )
But here the logic and operations for the download/upload are defined in the apiController. So before i am able to use these method, i first need to generate an ApplicationService. Before this is not done, i can't access these methods from other applicationservice.
So please explain, how you would write the ApplicationService/IApplicationService for the above code ?
Hi Maliming, do you imean i should use it like that ?:
 public Task<IRemoteStreamContent> Download(Guid id)
        {
            var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.OpenOrCreate);
            return Task.FromResult(
                (IRemoteStreamContent) new RemoteStreamContent(fs) {
                    ContentType = "application/octet-stream" 
                }
            );
        }
        public async Task Upload(Guid id, IRemoteStreamContent streamContent)
        {
            using (var fs = new FileStream("C:\\Temp\\" + id + ".blob", FileMode.Create))
            {
                await streamContent.GetStream().CopyToAsync(fs);
                await fs.FlushAsync();
            }
        }
Can you give me an example ?, because the method header wont match with above methodes, So should i then create an on applicationservice with above to be able to use it ?
For thos who also searched around for this infos:
My solution for filtering properties and id now looks like this.:
   public static class QueryableExtensions
    {
        public static Expression<Func<T, T>> DynamicSelectGenerator<T>(string filterProperties)
        {
            string[] entityProperties;
            if (filterProperties.IsNullOrEmpty())
                // get Properties of the T
                entityProperties = typeof(T).GetProperties().Select(propertyInfo => propertyInfo.Name).ToArray();
            else
            {
                // at least Id must be include besides a property (Case sensitive !)
                if (!filterProperties.Contains("Id"))
                    filterProperties +=",Id";
                    
                entityProperties = filterProperties.Split(',');
            }
            // input parameter "o"
            var xParameter = Expression.Parameter(typeof(T), "o");
            // new statement like "new Data()"
            var xNew = Expression.New(typeof(T));
            // create initializers
            var bindings = entityProperties.Select(o => o.Trim())
                .Select(o =>
                {
                // property "Field1"
                var mi = typeof(T).GetProperty(o);
                // original value "o.Field1"
                var xOriginal = Expression.Property(xParameter, mi);
                // set value "Field1 = o.Field1"
                return Expression.Bind(mi, xOriginal);
                }
            );
            // initialization "new Data { Field1 = o.Field1, Field2 = o.Field2 }"
            var xInit = Expression.MemberInit(xNew, bindings);
            // expression "o => new Data { Field1 = o.Field1, Field2 = o.Field2 }"
            var lambda = Expression.Lambda<Func<T, T>>(xInit, xParameter);
            // return expression
            return lambda;
        }
        // Extend IQuerable to use DynanimcSelector for Select
        public static IQueryable<T> Select<T>(this IQueryable<T> source, string parameters)
        {
            return source.Select(DynamicSelectGenerator<T>(parameters));
        }
        // Extend IQuerable to be able to use IncludeFilter
        public static IQueryable<T> IncludeFilter<T>(this IQueryable<T> queryable, List<Guid> filterIds, string filterProperties)
                where T : Entity<Guid>
        {
            return queryable
                .WhereIf(!filterIds.IsNullOrEmpty(), t => filterIds.Contains(t.Id))
                .Select(filterProperties);
        }
    }
Within an Repository i then call it like this, and also set Sorting (because DefaultSorting can fail if you omit the default parameter used for sorting) :
var query = ApplyFilter((await GetQueryableAsync()), filterText, name, description);
 // Add IncludeFilter to Query and adjust sorting
query = query.IncludeFilter(filterIds, filterProperties);
if (!filterProperties.IsNullOrEmpty())
  sorting = filterProperties.Split(",").First();
query = query.OrderBy(string.IsNullOrWhiteSpace(sorting) ? MyEntityConsts.GetDefaultSorting(false) : sorting);
return await query.PageBy(skipCount, maxResultCount).ToListAsync(cancellationToken);
To be able to use these both fields for my InputDto i used this:
 public class GlobalInputDto : PagedAndSortedResultRequestDto
    {
        /// Filter for specific Ids.
        public List<Guid> FilterIds { get; set; }
        /// Filter Properties (case-sensitive) p.E. "Name,Description,Id"
        public string FilterProperties { get; set; }
    }
To use it in for an Entity you only need to replacein your InputDtos PagedAndSortedResultRequestDto inheritance through GlobalInputDto
Hope this helps..
I thank you. I will take a look at it
Hi Ensin,
i thank you for your quick response. This works lika charm. Do you also got an idea for the second part on howto limit the properties with an paramter List<string> propertyList to generate a dynamic select statement which then can be added to the query like describes above.
Yes this would be great. If you share the Filemanager source i will contribute if i got it working it with chunk files and large files.
I dont got access to your source code.. So i will need to implement it my own. There are more things missing like progress etc.. It will take a look at devexpress componets we already got.
@maliming : Do you got a Chunkupload for large files in ABP ? I didn't use ABP Filemanager because i need to be able to upload big files like 50GB as chunkupload.. Maybe i could overwrite the upload method from abp for that.
I think i found the issue.. I use two Syncfusion Components in that example the Filemanager and a SfUploader , which can handle chunk uploads. After choosing files with the filemanager i cancel the upload through filemanager and start an upload with the sfupload. But although i cancel the upload from filemanager it seems it tries to start the upload before i cancel it and so it blocks the process.
If i only us the sfuploader it works..
So this error isn't abp specific altough this did work without Problem with 4.3.2. and this error occured after update to 4.4.2
I will see what i can found out. This error occured during my test on an Windows 10 machine with Visual Studio 2019 and 2022.. I did also Test on a different windows 10 machine. It also did occur there..
Did you test on windows 10 with visual studio ?
 
                                