Загрузка файла Excel приводит к его повреждению - PullRequest
0 голосов
/ 27 октября 2018

У меня есть простой сервис на Angular 2 и Typescript, который запрашивает файлы Excel на сервере, а затем открывает диалог загрузки файла для пользователя.Тем не менее, как и в настоящее время, файл становится поврежденным при загрузке.

При загрузке он нормально открывается в OpenOffice и создает его, но выдает ошибку «Файл поврежден» в Microsoft Excel и спрашивает, хочет ли пользовательвосстановить столько, сколько возможно.

Когда Excel предлагается восстановить файл, он делает это успешно, и восстановленный Excel имеет все строки и данные, которые ожидаются для файла Excel.Сравнение восстановленного файла с открытием файла в OpenOffice и получение свидетельств без существенных различий.

Конкретный Excel, который я пытаюсь загрузить, генерируется с помощью Apache POI в микросервисе, затем передается в основной бэкэнд и, наконец, обслуживаетсяинтерфейс для загрузки пользователем.И бэкэнд, и микросервис написаны на Java через Spark Framework.

Я провел несколько тестов на бэкэндах и пришел к выводу, что проблема не в генерации отчетов и передаче данных:

  1. Запрос микросервиса о сохранении сгенерированного Excel в файле на сервере и последующем открытии такого файла (настоящим файл A) в Excel показывает, что файл A не поврежден.

  2. Запрос основного внутреннего сервера сохранить файл Excel, который он получает от микросервиса, в файле внутри себя, а затем открыть такой файл в Excel (настоящий файл B), показывает, что файл B не поврежден.

  3. Загрузка файла A и файла B через FileZilla с соответствующих серверов приводит к появлению полностью не поврежденных файлов.

Таким образом, я считаю,можно предположить, что Excel поврежден где-то между временем получения файла на веб-интерфейсе и временем, когда пользователь загружает такой файл.Кроме того, журналы Catalina не указывают на какую-либо ошибку, которая потенциально может произойти.

Я прочитал несколько сообщений, касающихся этой проблемы, в том числе отчет об ошибке (https://github.com/angular/angular/issues/14083), который включает обходной путь через XMLHTTPRequestОднако ни одно из описанных обходных путей не помогло решить мою проблему.

Прикреплен код, который я использую как для получения файла Excel из серверной части, так и для его доставки пользователю. Я включаю оба XMLHTTPRequestи Angular http-вызов (в комментариях), так как это два основных способа, которыми я пытался сделать эту работу. Кроме того, пожалуйста, примите во внимание, что код был изменен, чтобы удалить информацию, которую я не хочу обнародовать.

download(body) {
    let reply = Observable.create(observer => {
      let xhr = new XMLHttpRequest();

      xhr.open('POST', 'URL', true);
      xhr.setRequestHeader('Content-type', 'application/json;charset=UTF-8');
      xhr.setRequestHeader('Accept', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
      xhr.setRequestHeader('Authorization', 'REDACTED');

      xhr.responseType = 'blob';

      xhr.onreadystatechange = function () {
        if(xhr.readyState === 4) {
          if(xhr.status === 200) {
            var contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
            var blob = new Blob([xhr.response], { type: contentType });
            observer.next(blob);
            observer.complete();
          }

          else {
            observer.error(xhr.response);
          }
        }
      }

      xhr.send(JSON.stringify(body));
    });

    return reply;


    /*let headers = new Headers();
    headers.set("Authorization", 'REDACTED');
    headers.set("Accept", 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');

    let requestOptions :RequestOptions = new RequestOptions({headers: headers, responseType: ResponseContentType.Blob});

    return this.http.post('URL', body, requestOptions);*/
  }

Здесь приведен код, предлагающий пользователю загрузить Excel. В настоящее время он настроен для работы с XMLHTTPRequest. Обратите внимание, что я также попытался загрузить, не прибегая к FileSaver, но не повезло.

downloadExcel(data) {
    let body = {
      /*REDACTED*/
    }

    this.service.download(body)
        .subscribe(data => {
          FileSaver.saveAs(data, "Excel.xlsx");
        });
  }

Здесь представлены версии инструментаs Я использую:

  • NPM: 5.6.0
  • NodeJs: 8.11.3
  • Угловой JS: ^ 6.1.0
  • БраузерыИспользуется: Chrome, Firefox, Edge.

Любая помощь по этому вопросу будет принята с благодарностью.Я буду рад предоставить любую дополнительную информацию, которая может вам понадобиться.

Ответы [ 2 ]

0 голосов
/ 27 октября 2018

Вы пробовали загрузить / загрузить файл xls как base64?

var encodedXLSToUpload = 'data:application/xls;base64,' + btoa(file);

Проверьте это для более подробной информации: Создание BLOB-объекта из строки base64 в JavaScript

0 голосов
/ 27 октября 2018

Я думаю, что вам нужен формат CSV, который открывается в Excel, обновите ваш сервис следующим образом:

Вы должны сообщить Angular, что вы ожидаете ответ типа blob (Binary Large Object), который является вашимФайл Excel / Csv.

Также убедитесь, что URL / API на вашем сервере настроен на прием content-type='text/csv'.

Вот пример с Angular 2.

@Injectable()
export class YourService {

    constructor(private http: Http) {}

    download() { //get file from the server
        this.http.get("http://localhost/..", {
            responseType: ResponseContentType.Blob,
            headers: new Headers({'Content-Type', 'text/csv'})
        }).subscribe(
            response => {
                var blob = new Blob([response.blob()], {type: 'text/csv'});
                FileSaver.saveAs(blob, 'yourFileName.csv');
            },
            error => {
                console.error('something went wrong');
            }
        );
    }
}
...