1

I already uploaded a file and saved the path into my database, but the problem now is that I can't download it. I have already tested the PHP code and it works, but when I try to download it from the Angular side it doesn't. Instead I get this error in the console:

httpErrorResponse error: SyntaxError: Unexpected token p in JSON at position 0
  at JSON.parse (<anonymous>)
  at XMLHttpRequest.onLoad (localhost:4200/vendor.js:164415:51)
  at ZoneDelegate.invokeTask (localhost:4200/polyfills.js:9799:31)
  .........

ANGULAR SERVICE:

public getjointes(filepath:string){
  const params = new HttpParams()
    .set('filepath', filepath);
  return this.http.get(url+'/download.php', {params: params });
}

TYPESCRIPT / function

telecharger(path:string) {
    console.log(path);
    this.stream.getjointes(path).subscribe(response => {
        console.log(response);
    });
}

PHP CODE:

$rest = $_GET['filepath'] ;

echo($rest);
$filepath = 'upload/' . $rest;

if (file_exists($filepath)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename=' . basename($filepath));
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize('upload/' . $rest));
    readfile('upload/' . $rest);
    header("Access-Control-Expose-Headers: Content-Disposition");   
}
else{
    echo ('noo');
}
miken32
  • 42,008
  • 16
  • 111
  • 154
mira
  • 11
  • 1
  • If you output anything (e.g. `echo($rest);`) then subsequent calls to `header()` are ignored. Ensure any calls to `header()` are made before *any* output. – miken32 May 19 '21 at 18:25
  • For future questions, please be sure to fully describe the problem you're having (not just "it doesn't work") and include appropriate error messages from your server logs. After checking your search engine of choice for solutions to those error messages of course. – miken32 May 19 '21 at 18:27
  • echo($rest) =>output: filename – mira May 19 '21 at 18:44
  • and in the console , it gives me a httpErrorResponse "error: SyntaxError: Unexpected token p in JSON at position 0 at JSON.parse () at XMLHttpRequest.onLoad (http://localhost:4200/vendor.js:164415:51) at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:9799:31) ......... – mira May 19 '21 at 18:49
  • window.open(‘download.php’)..? – MikeOne May 19 '21 at 18:56
  • response header: Access-Control-Allow-Credentials: true Access-Control-Max-Age: 1000 Content-Description: File Transfer Content-Disposition: attachment; filename=ppp-20210516123801.txt Expires: 0 Cache-Control: must-revalidate – mira May 19 '21 at 18:58
  • @MikeOne what do you mean – mira May 19 '21 at 18:58

1 Answers1

1

Ok I'm going to assume the echo statements in your PHP are just for testing, based on the error messages you included in comments.

I think the problem you're having is that Angular assumes the response will be JSON and attempts to parse it. To avoid this behaviour, you can set the responseType parameter to "text" or "blob" (for binary data) in your code:

public getjointes(filepath:string) {
    const params = new HttpParams()
      .set('filepath', filepath);
    return this.http.get(url+'/download.php', {params: params, responseType: "text"});
}

Note that any output before a call to header() will result in the HTTP header not getting set. Your PHP code calls header() after readfile(). That header will be ignored. In addition, if a file is not found you should say so with a proper 404 header. This way your client-side code can respond properly to failures. Your PHP should look like this:

$rest = $_GET['filepath'];
$filepath = 'upload/' . $rest;

if (file_exists($filepath) && is_readable($filepath)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename=' . basename($filepath));
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize('upload/' . $rest));
    header("Access-Control-Expose-Headers: Content-Disposition");   
    readfile('upload/' . $rest);
} else {
    header("HTTP/1.0 404 Not Found");
}
miken32
  • 42,008
  • 16
  • 111
  • 154
  • ok , now it just show me the the contents of the file in the console @miken32 – mira May 19 '21 at 19:41
  • Yes, you've subscribed to the response in your TypeScript and told it to do that: `console.log(response);` – miken32 May 19 '21 at 19:53
  • yeah i know but i still don't understand how i can download it @miken32 – mira May 19 '21 at 19:57
  • i know that my question is a little bit stupid but i'm beginner @miken32 – mira May 19 '21 at 20:14
  • Your Javascript code is downloading it. Do you want the end user to download it instead? Then you shouldn't be doing any of this. Just put a link like `Download` – miken32 May 19 '21 at 20:21