The OP did not know that the call was through AJAX.
Based on OP's own answer. In order not to save the archive to disk, you can do the following.
Instead of downloading and saving the file to POST. Save the necessary URLs for later use when creating the archive. A memory cache is an option.
Storage Abstraction Example
public interface IStorage { Task<T> GetAsync<T>(string key); Task SetAsync<T>(string key, T item); }
Any repository implementation should work after you can continue and then access the URLs after.
The implementation of the service may simply contain the necessary information.
private readonly IStorage cache; public async Task<string> CacheCarouselAsync(IEnumerable<Image> images) { var token = Guid.NewGuid().ToString(); await cache.SetAsync(token, images.Select(image => image.StandartResolutionURL).ToList()); return token; }
Upon publication, the media service will trade data for the token
[HttpPost, ValidateModel] public async Task<IActionResult> SaveCarousel([FromBody]CarouselViewModel model) { var token = await MediaService.CacheCarouselAsync(model.Images);
The URL to receive the archive will also be returned to call the client side.
$.ajax({ method: "POST", url: "/Media/SaveCarousel", data: requestData, contentType: "application/json; charset=utf-8", success: function (data) {
The GET action is only necessary to exchange the token for the generated zip file.
[HttpGet] public async Task<IActionResult> DownloadCarousel(string name) { var zip = await MediaService.DownloadAndZipCarousel(name); var filename = $"{zip.Name}.zip"; Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{filename}\""); return File(zip.Content, "application/zip"); }
The token will be used by the service to retrieve URLs from the repository, then download the carousel and create an archive.
public async Task<File> DownloadAndZipCarousel(string token) { //Get the model data from storage var images = await cache.GetAsync<IEnumerable<string>>(token); var client = CreateClient(); var file = new File(); var random = new Random(); using (var archiveStream = new MemoryStream()) { using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, false)) { foreach (var uri in images) { var imagename = $"Instagram{random.Next()}.jpg"; var archiveEntry = archive.CreateEntry(imagename, CompressionLevel.Optimal); using (var entryStream = archiveEntry.Open()) { using (var contentStream = await client.GetStreamAsync(uri)) { await contentStream.CopyToAsync(entryStream); } } } } file.Name = "RandomZip"; //TODO: derive a better naming system file.Content = archiveStream.ToArray(); } return file; }