How to upload and download the same request using AngularJS and Web api?

3

I'm developing a feature that will receive a spreadsheet in .xlsx format, perform a render and return that spreadsheet with the columns added, in which case I should upload a file and success would download it. In my attempts or I can send the file or just receive I still can not get the two without corrupting the return file, in the following code I can receive the file, perform the processing and download however the file is corrupted, I do not believe

asked by anonymous 21.07.2016 / 15:00

1 answer

1

I was able to solve it, here's the code, I'm using Angular Material , so the 'apsUploadFile' directive to leave the button of the input file in the style of the material design.

Angular

    app.controller('processoCtrl', function ($scope, $http, $location) {

        function send(data, uploadUrl, success, error) {
                var fd = new FormData();
                for (var key in data) {
                    fd.append(key, data[key]);
                }
                return $http.post(uploadUrl, fd, {
                    headers: { 'Content-Type': undefined },
                    responseType: 'arraybuffer'
                });
            };

        $scope.uploadArquivo = function (data) {
                var upload = { data: data };
                var uploadUrl = 'api/enviaraquivo';
                var nomearquivo = $('input').val().split('\')[2].split('.')[0];
                send(upload, uploadUrl).
                    then(function (result, status, xhr) {
                        $scope.actived = !$scope.actived;
                        $scope.publicacaonaoencontrada = false;
                        $("#upload").prop('disabled', false);
                        var filename = nomearquivo + '_Analisada_.xlsx';
                        var blob = new Blob([result.data], { type:     "application/octet-stream" });
                        if (typeof window.navigator.msSaveBlob !== 'undefined') {
                            // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
                            window.navigator.msSaveBlob(blob, filename);
                        } else {
                            var URL = window.URL || window.webkitURL;
                            var downloadUrl = URL.createObjectURL(blob);

                            if (filename) {
                                // use HTML5 a[download] attribute to specify filename
                                var a = document.createElement("a");
                                // safari doesn't support this yet
                                if (typeof a.download === 'undefined') {
                                    window.location = downloadUrl;
                                } else {
                                    a.href = downloadUrl;
                                    a.download = filename;
                                    document.body.appendChild(a);
                                    a.click();
                                }
                            } else {
                                window.location = downloadUrl;
                            }

                            setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100);
                        }
                       alert('arquivo processado com sucesso');
                    }, function (result) {
                        $("#upload").prop('disabled', false);

                        if (result.status == 401) {
                            alert('acesso não autorizado, realize o login');
                        } else {
                            alert('Arquivo fora dos padrões');
                        }

                    });
            }
    }).directive('apsUploadFile', apsUploadFile);
//Código para colocar um design material no input file

function apsUploadFile() {
    var directive = {
        restrict: 'E',
        template: '<input id="upload"  accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" type="file" class="ng-hide" file-model="upload">' +
            ' <md-button id="uploadButton" class="md-raised md-primary" aria-label="attach_file"> Carregar planilha </md-button>' +
            '<md-input-container class="input-file-text" md-no-float><input id="textInput" ng-model="fileName" type="text" placeholder="Nenhum arquivo selecionado" ng-readonly="true"></md-input-container>' +
            '<md-button class="md-raised md-primary" ng-disabled="upload == null" ng-click="uploadArquivo(upload)">Upload</md-button>',
        link: apsUploadFileLink
    };
    return directive;
}

function apsUploadFileLink(scope, element, attrs) {
    var input = $(element[0].querySelector('#upload'));
    var button = $(element[0].querySelector('#uploadButton'));
    var textInput = $(element[0].querySelector('#textInput'));

    if (input.length && button.length && textInput.length) {
        button.click(function (e) {
            input.click();
        });
        textInput.click(function (e) {
            input.click();
        });
    }

    input.on('change', function (e) {
        var files = e.target.files;
        if (files[0]) {
            scope.fileName = files[0].name;
        } else {
            scope.fileName = null;
        }
        scope.$apply();
    });
}

View

<div ng-controller="processoCtrl as processo">
    <div class="upload-page">
        <div class="form">
            <form method="post" target="hidden-form">
                <h2>Carregue o arquivo</h2>
                <div class="form">
                    <div class="input-group">
                        <md-content layout-padding layout="row" layout-align="start end">
                            <aps-upload-file style="text-align: center;"></aps-upload-file>
                        </md-content>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>

Controller Web Api

 [HttpPost]
    [Route("enviararquivo")]
    public async Task<HttpResponseMessage> PostArquivo()
    {

        if (!Request.Content.IsMimeMultipartContent())
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);

        try
        {
            CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("~/App_Data"));
            await Request.Content.ReadAsMultipartAsync(provider);

            MultipartFileData file = provider.FileData.FirstOrDefault();

            FileInfo info = new FileInfo(file.LocalFileName);
            var planilhaDaRequisicao = new ExcelPackage(info);
            MemoryStream streamPlanilhaRequisicao = new MemoryStream();
            planilhaDaRequisicao.SaveAs(streamPlanilhaRequisicao);

            var streamPlanilhaAnalizada = servicePublicacao.VerificaPublicacao(streamPlanilhaRequisicao);
            var result = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ByteArrayContent(streamPlanilhaAnalizada.GetBuffer())
            };
            result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
            {
                FileName = $"download{ DateTime.Now }.xlsx"
            };

            return result;
        }
        catch (Exception ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Arquivo fora dos padrões para consulta");
        }
    }

For spreadsheet processing I'm using the EPPlus library.

    
29.07.2016 / 13:45