Open Closed

Can API return a file? #4529


0
fguo created

I am using Core + Angular version, and need to return a file (.jpg, .xlsx, .pdf, and so on) to client site. It seems that our API can ONLY return a JSON object, as I know. Is it possible to return a file?

Thanks,


7 Answer(s)
  • 0
    drenton created

    Search for "FileDownloadService" in angular project and "FileController" in .Net Core project

  • 0
    fguo created

    @drenton Thank you for your clue.

    I found the class of "FileDownloadService" and "FileController", and studied some examples (e.g. getUsersToExcel). It seems to convert a file into a FileDto and return this FileDto as JSON format {"fileName", "fileType", "fileToken"}, but I still couldn't understand how to convert a file content to "fileToken" in server side and how to convert back the FileDto to original file and save it on client side.

    Is there any instruction/tutorial/example about it? Let's say, I have a file example.jpg stored in folder App_Data. How do I build a service on both of Core and Angular sides?

    Thanks,

  • 0
    ismcagdas created
    Support Team

    @fguo the file is requested from a Controller at the end of this scenario by the angular client. So, I suggest you to use a controller.

  • 0
    fguo created

    Sorry, still don't understand. My need is simple: I have a file "x.jpg" stored in server folder "C:/Files/". How do I code something to let user download it to client side? Can you show me an code example?

    I also need to deal other use-cases about files soon, such as embedding a file (e.g. a picture) into json object, and uploading files into server. I wonder if AspNetZero have built-in functions or easy-to-follow instructions about file handling. If not, it is understandable. I may stop digging it in AspNetZero and try other alternatives for handling files. Can you clarify this?

    Thank you!

  • 0
    fguo created

    I figured out my first question, but not 100%. Here is my tests:

    I like to keep as simple as possible at my first test. I created a method in FileController:

    public ActionResult DownloadTestFile()
            {
                var filePath = @"C:\x.xlsx";
                if (!System.IO.File.Exists(filePath))
                {
                    throw new UserFriendlyException(L("RequestedFileDoesNotExists"));
                }
    
                var fileBytes = System.IO.File.ReadAllBytes(filePath);
                return File(fileBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); 
            }
    

    It works fineas I use a browser and url: <a class="postlink" href="http://localhost:22742/File/DownloadTestFile">http://localhost:22742/File/DownloadTestFile</a>.

    Now, I want to add a fileToken on it. I created a service:

    public class FileAppService : *AppServiceBase, IImageAppService
        {
            private readonly IAppFolders _appFolders;
    
            public FileAppService(IAppFolders appFolders)
            {
                _appFolders = appFolders;
            }
    
            public FileDto GetFile()
            {
                var fileSource = @"C:\x.xlsx";
                var fileName = "example.xlsx";
                var file = new FileDto(fileName, MimeTypeNames.ApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheet);
                var filePath = Path.Combine(_appFolders.TempFileDownloadFolder, file.FileToken);
                if (!Directory.Exists(filePath))
                    Directory.CreateDirectory(filePath);
                File.Copy(fileSource, Path.Combine(filePath, fileName));
    
                return file;
            }
        }
    

    This service works fine. When I test it on swager, it give out a FileDto:

    "result": {
        "fileName": "example.xlsx",
        "fileType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "fileToken": "9a864412394442758089b4256029cd48"
      }
    

    I confirmed It copies the file on C:\aspnet-core\src\SNet.Web.Host\wwwroot\Temp\Downloads\9a864412394442758089b4256029cd48\example.xlsx

    However, when I try to download the file by url: <a class="postlink" href="http://localhost:22742/File/DownloadTempFile?fileType=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet&fileToken=9a864412394442758089b4256029cd48&fileName=example.xlsx">http://localhost:22742/File/DownloadTem ... ample.xlsx</a>,I get exception on code:

    throw new UserFriendlyException(L("RequestedFileDoesNotExists"));
    

    What did I miss? Does the "_appFolders.TempFileDownloadFolder" in FileController point to a different location?

    Thanks,

  • 0
    fguo created

    Solved. I wrongly understand the "FileToken". It is used as an encrypted file name, instead of a directory.

    Just change the code:

    if (!Directory.Exists(filePath))
                    Directory.CreateDirectory(filePath);
                File.Copy(fileSource, Path.Combine(filePath, fileName));
    

    as

    File.Copy(fileSource, filePath);
    

    It solved my issue.

    Now, my next questions:

    1. How do I upload files from Angular into server?
    2. Is it possible to embed a file (e.g. a picture) into json object? For example, API returns like { "id": 123, "picture": {/* a jpg file */} }

    Thanks,

  • 0
    ismcagdas created
    Support Team

    Hi @fguo,

    Thank you for sharing your solution. You can check demo ui components page for file upload example.