webForumDet fria alternativet

Får inte rätt på tvingad nedladdning

PHP

23 svar · 1 610 visningar · startad av maweer

Medlem sedan juli 2012123 inlägg
Frågan#1

Hur jag än gör med mina headers så laddar den ner rätt men en "tom" fil.

Vad gör jag för fel?

Här är min kod som anropar get_file.php

<?php 

include "conn.php"; 

$sql = mysql_query("SELECT * FROM musik ORDER BY datum DESC LIMIT 50"); 
while ($rad = mysql_fetch_array($sql))

 {
   
  $id = $rad['id'];
  $fil = $rad['fil'];
  $datum = $rad['datum']; 

  echo("<img src=\"images/'.$type.'.gif\">&nbsp;&nbsp;<a href=\"get_file.php/{$rad['fil']}\">Ladda ner</a>");
  echo("&nbsp; - &nbsp;");
  echo($rad['datum']);
  echo("<br>");

  
} 

?>

Och här är get_file.php som då är tänkt skall fixa till nedladdningen

<?php 
header("Cache-control: private");
header("Content-Type: application/octet-stream");
header("Content-Length: ".filesize("./bilder/".$fil));
header("Content-Disposition: attachment; filename=".$fil);
$fp = fopen("./bilder/".$fil, "rb");
fpassthru($fp);
exit;
?>
Medlem sedan jan. 2005953 inlägg
#2

Var får $fil sitt värde i get_file.php?

Medlem sedan juli 2012123 inlägg
#3

Det borde väl vara genom $fil = $rad['fil'];

Jag har en form som lagrar filerna på en plats och filnamnen i tabellen i DB.
Sen hämtar jag filen via <a href=\"{$rad['fil']} och då blir det ju en helt vanlig länk.
Men, så tänkte jag att jag använder headers för att tvinga nedladdningen och då la jag till get_file.php

Medlem sedan jan. 2005953 inlägg
#4

Nej, $fil = $rad['fil']; ligger ju i den filen som anropar get_file.php

Medlem sedan juli 2012123 inlägg
#5

Hmmmm....aha!
Då vet jag inte om sanningen skall fram. Jag trodde att det var så!
Den hämtar ju värdet från DB väl...(Hoppas jag)

Medlem sedan jan. 2005953 inlägg
#6

Ok, lova att du sätter dig in i koden för att förstå den. Inte bara klippa och klistra ;)

nånfil.php

<?php 
include "conn.php"; 

$sql = mysql_query("SELECT * FROM musik ORDER BY datum DESC LIMIT 50"); 
while ($rad = mysql_fetch_array($sql)) {
    $id = $rad['id'];
    $fil = $rad['fil'];
    $datum = $rad['datum']; 

    /* I raden nedan så används $type ... den variabeln verkar inte finnas enligt koden ... men jag lät den vara med i alla fall :D */
    echo '<img src="images/' . $type . '.gif">&nbsp;&nbsp;<a href="get_file.php?file=' . $fil . '">Ladda ner</a>";
    echo "&nbsp; - &nbsp;";
    echo $datum;
    echo "<br>";
} 
?>

get_file.php

<?php
$fil = isset($_GET['file']) ? basename($_GET['file']) : false;
if ($fil && file_exists('./bilder/' . $fil)) {
    header("Cache-control: private");
    header("Content-Type: application/octet-stream");
    header("Content-Length: " . filesize("./bilder/".$fil));
    header("Content-Disposition: attachment; filename=" . $fil);
    $fp = fopen("./bilder/" . $fil, "rb");
    fpassthru($fp);
    fclose($fp);
    exit;
} else {
    die('File not found');
}
?>

Observera att koden är otestad, men jag tror att den fungerar i alla fall ;)

ÄNDRAT:
Hade råkat skriva $file istället för $fil i get_file.php

Medlem sedan juli 2012123 inlägg
#7

du milde vad du var snabb :)

nånfil.php blev lite konstig tyvärr. Den hämtade inte ut några fil namn och så hämtade den bara ut en fil, så jag provade med den gamla koden, vilket jag tror inte var tanken med det hela faktikst. För jag misstänker väl att det är i min kod i den som felet ligger.

get_file.php
gick den direkt in i else-satsen (file not found)

Medlem sedan jan. 2005953 inlägg
#8

Det enda du behöver ändra i din kod som hämtar info från db är följande

get_file.php/{$rad['fil']}

ska vara

get_file.php?file={$rad['fil']}

PS. Har du sett att ett litet slarvfel smög sig in i koden för get_file.php? Ändrat nu. DS

Medlem sedan juli 2012123 inlägg
#9

Hahaha ja jösses du är en klippa!!!! :) :) Det funkar sååååå kanon!

Alltså jag har suttit med detta i två dagar och inte fattat ett smack vad som händer!
Hmmmmm...sätta sig in i koden ja :) Hehehe, skall jag vara ärlig....hur gjorde du? :P
Du får jätte gärna förklara för mig :)

.$type. som du frågade om innan är att jag hade tänkt att ha en specifik ikon vid den specifika bilden. Alltså .gif en ikon för det och .jpg en ikon för det.

Tjo....du undrar inte hur glad du gjorde mig precis!
Tack!!!!!!!!!!!!

Medlem sedan juli 2012123 inlägg
#10

Som du märker är jag väldigt nybörjare på detta och det tog mig ett rätt bra tag att bara få rätt på den första koden

Medlem sedan jan. 2005953 inlägg
#11

Bra att du blev nöjd. Angående kodförståelsen, är det något specifikt du vill att jag förklarar?

Medlem sedan juli 2012123 inlägg
#12

Jag blev mer en nöjd...jag blev jätte glad :)

Jo, det var väl i princip hela första raden

$fil = isset($_GET['file']) ? basename($_GET['file']) : false;

som jag funderade mest på.

och sen basename() har jag sett många använder men aldrig blivit klok på användningsområdet

I vilket fall som helst så...ett stort tack!

Medlem sedan jan. 2005953 inlägg
#13
$fil = isset($_GET['file']) ? basename($_GET['file']) : false;

är ett sätt att skriva en if-else-sats på.
Man hade lika gärna kunna skriva

if (isset($_GET['file'])) {
    $fil = basename($_GET['file']);
} else {
    $fil = false;
}

Syntaxen är alltså
condition ? if true : if false

Det nämns lite hastigt i följande manualsida under namnet ternary conditional operator:
http://se.php.net/manual/en/language.expressions.php

basename() plockar ut själva filnamnsdelen ur en sökväg. Jag la in det i koden för att förhindra att någon ska kunna ladda ner vilken fil som helst från din server. Tänk t.ex. om någon anger get_file.php?file=../index.php, scriptet skulle då låta besökaren ladda ner filen ./bilder/../index.php, dvs din index-fil, och det är nog inte önskvärt.

basename('../index.php') returnerar 'index.php'.

Läs mer om funktionen i manualen på sidan http://www.php.net/basename

Manualen är förresten en ypperlig källa till kunskap när man programmerar PHP. Vilken funktion du än är osäker på så skriver du bara adressen http://www.php.net/funktionsnamn i adressfältet i din webbläsare så kan du läsa om funktionen, vilka parametrar den tar och vad den returnerar tillsammans med några exempel på hur den används.

Medlem sedan juli 2012123 inlägg
#14

Oj, det var mycket matnyttigt :)
Då är det mao lite farligt att inte använde sig av basename() i sökvägar.

Skall ta till mig av alla tipsen och hoppas att jag kommer ihåg det när jag behöver det igen :)

Medlem sedan jan. 2005953 inlägg
#15

Det som är farligt är att utgå ifrån att bara snällt data kommer in till scriptet.
All data som besökaren på något sätt kan manipulera, oavsett om det är via GET, POST eller COOKIE, så måste du validera att datat är det du förväntar dig. Scriptet blir alltså inte farligt bara för att du inte använder basename(), men du måste kontrollera och tvätta bort sånt som kan vara farligt.

Googla t.ex. på SQL injection så kommer du finna ganska mycket som är läsvärt.

Medlem sedan juli 2012123 inlägg
#16

Tack :) Det skall jag verkligen göra!

Tack för tipset om manualen förresten :)

Har försökt med manualens hjälp och lite snodd kod från andra sidor att få till min variabel $type som är tänkt att visa en specifik bild för gif, en för jpg....etc
Men, det blev inte riktigt som jag hade tänkt mig hahaha

jag tänkte öppna mappen som filerna ligger

$dir = opendir("bilder/");

Så här skrevs det i manualen att man var tvungen till att göra med readdir()

while (false !== ($files = readdir($dir))) {

Listar alla filer och filtyper

list($files, $type) = explode(" ", $files);

Skriver ut bilderna för de olika filtyperna

echo '<img src="images/icon'.$type.'.gif"><br>';

Avslutar och stänger

}

closedir($dir);

Så långt funkar det (om jag gör det utan min andra kod)....hmmm :r

Så när jag lägga ihop mina två skript:

<?php 
include "conn.php"; 

$sql = mysql_query("SELECT * FROM musik ORDER BY datum DESC LIMIT 50"); 
while ($rad = mysql_fetch_array($sql))
 {
  $id = $rad['id'];
  $fil = $rad['fil'];
  $datum = $rad['datum'];

$dir = opendir("bilder/");
while (false !== ($files = readdir($dir))) {
list($files, $type) = explode(" ", $files);

  echo("<img src=\"images/icon'.$type.'.gif\">&nbsp;&nbsp;<a href=\"get_file.php?file={$rad['fil']}\">Ladda ner</a>");
  echo("&nbsp; - &nbsp;");
  echo($rad['datum']);
  echo("&nbsp; - &nbsp;");
  echo($rad['fil']);
  echo("<br>");
} 
}
closedir($dir);
?>

Så listar den ut alla filerna 20 gånger utan bilder.
Jag misstänker att jag inte gjort rätt hahahaha :)

Medlem sedan jan. 2005953 inlägg
#17

Oj, vad exakt är det du vill åstadkomma? :)

Medlem sedan juli 2012123 inlägg
#18

Hahahaha :)
Jo, att man öppnar mappen bilder och läser av vilka filtyper som finns i mappen.

Sen var tanken att den "skriver ut" och visar en ikon för varje post och om det är en gif-fil så visas ikonen icongif.gif, och om det är en jpg-fil så visas ikonen iconjpg.gif.
Där av min konstiga $type

echo("<img src=\"images/icon'.$type.'.gif\">&nbsp;&nbsp;<a href=\"get_file.php?file={$rad['fil']}\">Ladda ner</a>");
Medlem sedan jan. 2005953 inlägg
#19

Men filnamnen hämtas väl fortfarande från databasen?
Då behöver du inte öppna någon mapp och läsa innehållet.

Testa följande:

<?php 
include "conn.php"; 

$sql = mysql_query("SELECT * FROM musik ORDER BY datum DESC LIMIT 50"); 
while ($rad = mysql_fetch_array($sql))
 {
  $id = $rad['id'];
  $fil = $rad['fil'];
  $datum = $rad['datum'];
  $type = pathinfo($fil, PATHINFO_EXTENSION);

  echo("<img src=\"images/icon'.$type.'.gif\">&nbsp;&nbsp;<a href=\"get_file.php?file={$rad['fil']}\">Ladda ner</a>");
  echo("&nbsp; - &nbsp;");
  echo($rad['datum']);
  echo("&nbsp; - &nbsp;");
  echo($rad['fil']);
  echo("<br>");
}
?>

http://www.php.net/pathinfo

Medlem sedan juli 2012123 inlägg
#20

Jo, det har du ju rätt i :)
Aha så du får ut iformationen i mappen med

  $type = pathinfo($fil, PATHINFO_EXTENSION);

Coolt....trodde jag behövde all den koden som jag skrev :)
Man kan ju lugnt säga att min kod var lite klumpigare hahaha

Tyvärr får jag inte fram några ikoner, men nu ser ju sidan i alla fall sidan ut som den skall göra igen:)

262 ms totalt · 4 externa anrop · v20260731065814-full.6fe65c25
122 ms — deklarationer (db)
0 ms — hämta statistik (cache)
138 ms — hämta tråd, inlägg och bilagor (db)
122 ms — ändringar (db)