Home Downloading file from windows server works, but from linux not - HTTP 406 error
Reply: 0

Downloading file from windows server works, but from linux not - HTTP 406 error

user6023
1#
user6023 Published in July 22, 2018, 8:57 am

I am trying to implement functionality for downloading files with logs from server to client station.

My solution works good on Windows 10 when I am testing in my local environment. But when I move it to linux server, it doesen't work.

For example: If we open web page with logs, we should get log's names list. After click on log name, downloading file is started an we can save log file to read it. This works fine on widnows - localhost.

On linux, everything works until the moment of clicking on file from list to try to download it.

Communication between server and client is implemented via REST API. Path to logs is correct, both in linux and widows. Logs names and path to them is always correct.

My question is: What could be cause of this problem?

Console error below:

ERROR 
{…}
​
_body: "{\"timestamp\":1523867122045,\"status\":406,\"error\":\"Not Acceptable\",\"exception\":\"org.springframework.web.HttpMediaTypeNotAcceptableException\",\"message\":\"Could not find acceptable representation\",\"path\":\"/{...}/api/logs/MyLogFile.log\"}"
​
headers: Object { _headers: Map, _normalizedNames: Map }
​
ok: false
​
status: 406
​
statusText: "OK"
​
type: 2
​
url: "http://{...}/api/logs/MyLogFile.log"
​
__proto__: Object { constructor: Response(), toString: toString() }

Front-end side

log.component.html

<div class="container">
 <div class="col s4" ng-controller="PostsCtrl">
    <ul>
      <li *ngFor="let log of logFilesNames;">
       <a class="pointer" (click)="getLogFileContent(log)">{{log}}</a>
      </li>
    </ul>
  </div>
</div>

log.component.ts

import { Component, OnInit } from '@angular/core';
import { LogsService } from '../_services/logs.service';
import { saveAs } from 'file-saver';
import { Logs } from '../_models/Logs';

@Component({
  selector: 'logs',
  styleUrls: ['logs.component.css'],
  templateUrl: './logs.component.html'
})

export class LogsComponent implements OnInit {

  private logFilesNames: string;
  private logs: Logs;

  constructor(private logsService: LogsService) {}

  public ngOnInit(): void {
    this.getLogFilesNamesList();
  }

  private getLogFilesNamesList() {
    this.logsService.getLogFilesNamesList()
      .subscribe((response) => {
        this.logFilesNames = response;
      });
  }

  private getLogFileContent(logFileName: string) {
    this.logsService.getLogFileContent(logFileName)
      .subscribe((response) => {
        this.logs = response;
        this.saveFile(logFileName);
      });
  }

  private saveFile(logFileName: string) {
    let file = new File([atob(this.logs.logResponse.toString())],
      logFileName, {type: 'text/plain;charset=utf-8'});
    saveAs(file);
  }
}

log.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Logs } from '../_models/Logs';

@Injectable()
export class LogsService {
  private url = '/api/logs';

  constructor(private http: Http) {}

  public getLogFilesNamesList(): Observable<string> {
    return this.http.get(this.url)
      .map(this.extractData);
  }

  public getLogFileContent(logFileName: string): Observable<Logs> {
    const url = `${this.url}/${logFileName}`;
    return this.http.get(url)
      .map(this.extractData);
  }

  private extractData(res: Response) {
    let body = res.json();
    return body || [];
  }
}

Logs.ts

import { Binary } from '@angular/compiler';

export class Logs {

  public logResponse: Binary[];

  constructor(log: Binary[]) {
    this.logResponse = log;
  }
}

Back-end side

LogResponse.java

import lombok.AllArgsConstructor;

@AllArgsConstructor
public class LogResponse {
   public byte[] logResponse;
}

LogsApi.java

@RestController
@RequestMapping("/api/logs")
@Slf4j
@Log4j
public class LogsApi {

   private static final File LOGS_FOLDER = new File(getPathToLogFolder());
   private static final String LOG_EXTENSION = ".log";

   @GetMapping
   @ApiOperation(value = "Getting all logs files names")
   public HttpEntity<List<String>> getListOfLogNames() {
      File[] logFiles = LOGS_FOLDER.listFiles();
      return ResponseEntity.ok(getListOfLogNames(logFiles));
   }

   private List<String> getListOfLogNames(File[] logFiles) {
      if (nonNull(logFiles)) {
         return Arrays.stream(logFiles).map(File::getName)
                     .filter(fileName -> fileName.endsWith(LOG_EXTENSION))
                     .sorted(Comparator.reverseOrder()).collect(Collectors.toList());
      } else {
         return emptyList();
      }
   }

   @GetMapping("/{logFileName}")
   @ApiOperation(value = "Get file with logs written in bytes")
   public HttpEntity<LogResponse> getLogFile(@PathVariable String logFileName) throws IOException {
      Path fileLocation = Paths.get(getPathToLogFile(logFileName));
      LogResponse logResponse = new LogResponse(Files.readAllBytes(fileLocation));
      return ResponseEntity.ok().body(logResponse);
   }

   private String getPathToLogFile(@PathVariable String logFileName) {

      return LOGS_FOLDER + getSlashBasedOnOperatingSystem() + logFileName + LOG_EXTENSION;
   }

   private static String getPathToLogFolder() {
      OSDetector osDetector = new OSDetector();
      return osDetector.isWindows() ? "\\windows\\path" : "/linux/path";
   }

   private static String getSlashBasedOnOperatingSystem() {
      OSDetector osDetector = new OSDetector();
      return osDetector.isWindows() ? "\\" : "/";
   }
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.312593 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO