CURL befehl zum speichern eines Videos

Hallo

Ich bin gerade dabei mein IPS von Windows auf die Synology in einem Docker Container zu portieren.

unter Windows habe ich nach Auswertung der Kameradaten und erzeugen einer XML-Datei eine Batchdatei wie folgt erzeugt und diese dann aus einem Script gestartet um ein Video in einem definierten Zeitraum herunterzuladen

curl -X GET -d @Datei.xml http://User:PW@IP:Port/ISAPI/ContentMgmt/download >v:/Kamera1-20191114T204258.mp4

nun kann ich aber innerhalb de IPS im Docker Container keine Scriptdatei erzeugen, da offensichllich es ein Rechteproblem gibt bzw ich nicht weiß, welche Rechte auf welche Verzeichnisse gestzt sind

wie bekomme ich die Funktion direkt in ein PHP-Script ?

curl -X GET -d @datei.xml http://User:PW@IP:Port/ISAPI/ContentMgmt/download >/home/cams/aufnahmen/Kamera1-20191114T204258.mp4

liefert

Parse error: syntax error, unexpected ‚GET‘ (T_STRING) in /var/lib/symcon/scripts/52175.ips.php on line 148
Abort Processing during Fatal-Error: syntax error, unexpected ‚GET‘ (T_STRING)
Error in Script /var/lib/symcon/scripts/52175.ips.php on Line 148

wobei /home/cams/aufnahmen ein Verzeichnis ist, das für den IPS Docker container gemappt ist.

PHP: Beispiele - Manual

Hallo Titus,

wenn ich da was passendes gefunden hätte, hätte ich das Thema nicht erstellt :slight_smile:

es geht hier um die Umsetzung von Curl für Windows/Unix auf Curl PHP und darum das Ausgabefile aus dem IPS im Dockercontainer in einem Verzeichnis zu speichern, das direkt aus dem NAS-Filesystem gelesen werden kann.

@downloadrequestips.xml ist ein request-XML-file was auch in einer Variablen unter IPS bereitgestellt werden kann
Die erzeugten Videodateien sind bis 100 MB groß

Leider funktioniert eine Lösung über ein Bash script derzeit nicht, da beim aufruf des shellsripts von IPS aus eine leere Datei geschrieben wird, da offensichlich die Eingabe-XML-Datei @downloadrequestips.xml nicht gelesen werden kann, obwohl diese im script-Verzeichnis von IPS liegt und das script ja aus script-Verzeichnis gestartet wird.

Wenn ich mich als root im NAS einlogge, funktioniert alles perfekt.

Fall sich jemand mit der Rechtevergabe in Docker-containern auskennt oder weiß, wo man Quelldateien ablegen muß, damit die beim start eines scripts gelesen werden können, wäre mir sehr geholfen :slight_smile:

hier nochmal die Doku von Curl für windows

// curl -X GET -d @downloadrequestips.xml http://User:Pw@IP:Port/ISAPI/ContentMgmt/download >/ Speicherpfad / Eingang20191115T150323.mp4

// -X, --request <command>
// (HTTP) Specifies a custom request method to use when communicating with the HTTP server.
// The specified request method will be used instead of the method otherwise used (which defaults to GET). Read the HTTP 1.1 specification for details and explanations.
// Common additional HTTP requests include PUT and DELETE, but related technologies like WebDAV offers PROPFIND, COPY, MOVE and more.
// Normally you don’t need this option. All sorts of GET, HEAD, POST and PUT requests are rather invoked by using dedicated command line options.

// -G, --get
// When used, this option will make all data specified with -d, --data, --data-binary or --data-urlencode to be used in an HTTP GET request instead of the POST
// request that otherwise would be used. The data will be appended to the URL with a ‚?‘ separator.
// If used in combination with -I, --head, the POST data will instead be appended to the URL with a HEAD request.

// -d, --data <data>
// (HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form
// and presses the submit button. This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded.
// Compare to -F, --form.
// If you start the data with the letter @, the rest should be a file name to read the data from,
// or - if you want curl to read the data from stdin. Multiple files can also be specified.
// Posting data from a file named ‚foobar‘ would thus be done with -d, --data @foobar. When --data is told to read from a file like that, carriage returns and newlines will be stripped out.
// If you don’t want the @ character to have a special interpretation use --data-raw instead.

habe mal dieses probiert:


$path2 = ‚/ISAPI/ContentMgmt/download‘; // Downloadbefehl für Kamera

$videoname= GetValueString(10479);

$composedUrl=$prefix.$user.$colon.$pass.$at.$host.$colon.$port.$path2;
CurlOperation($composedUrl,$videoname,$xml_data1,$downloadrequest);

function CurlOperation($curlUrl,&$videoname,&$xml_data1,&$downloadrequest)
//function CurlOperation($curlUrl,&$xml_data,&$suchbefehl)
{
$result= „“;
$curlOptions = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => ‚GET‘
);

   $ch = curl_init($curlUrl);
   curl_setopt_array($ch, $curlOptions);
   curl_setopt($ch, CURLOPT_POST, true);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   curl_setopt($ch, CURLOPT_POSTFIELDS, $downloadrequest);
   
   $xml_data=curl_exec($ch);	
   file_put_contents ($videoname,$xml_data1);

return $xml_data1;

curl_close($ch);
}

liefert - wobei IPS da erstmal für 10 Sekunden beschäftigt ist - den Fehler:

Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 14684160 bytes) in C:\ProgramData\Symcon\scripts\28924.ips.php on line 47
Abort Processing during Fatal-Error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 14684160 bytes)
Error in Script C:\ProgramData\Symcon\scripts\28924.ips.php on Line 47

Aufnahmedownload_test.txt (1.06 KB)

Es ist nicht clever die Datei erst in den RAM zu laden und dann auf die Festplatte. Da du unter Docker wahrscheinlich weniger RAM zur Verfügung hast, limitiert IP-Symcon deinen PHP Thread auf 32MB.

Lade die Daten einfach nach und nach runter und werfe die direkt auf die Platte.
Beispiel hier: Download large file from the web via php · GitHub

paresy

hallo paresy,

…deshalb habe ich es ja ursprünglich mit einer Batchdatei unter Window sbzw versucht mit einem Shellscript auf der Synology zu lösen - leider kann ich aber beim Aufruf des Shellscripts das Definitionsfile nicht lesen ( vermutlich wegen der Rechte unter dem Dockercontainer) bzw den String „downloadrequest“ nicht übergeben

leider bringt sowohl das von Dir vorgeschlagene Script bzw auch die modifizierte nachfolgende Version



$dest= GetValueString(10479);
$dest="c:/test.mp4";
$url=$prefix.$user.$colon.$pass.$at.$host.$colon.$port.$path2;
$downloadrequest=GetValueString(24307);

echo $downloadrequest;


public static function downloadDistantFile($downloadrequest, $url, $dest)

  {

    $options = array(

      CURLOPT_FILE => is_resource($downloadrequest,$dest) ? $dest : fopen($dest, 'w'),

      CURLOPT_FOLLOWLOCATION => true,

      CURLOPT_URL => $url,

      CURLOPT_FAILONERROR => true,  // HTTP code > 400 will throw curl error

        curl_setopt($ch, CURLOPT_POSTFIELDS, $downloadrequest)
 );

    $ch = curl_init();

      //  fclose($dest);  ????
 
     $return = curl_exec($ch);

    if ($return === false)

    {
      return curl_error($ch);
    }

    else

    {
      return true;
    }

  }


folgenden Fehler: ( Zeile 41 ist public static function downloadDistantFile($downloadrequest, $url, $dest);

Parse error: syntax error, unexpected ‚public‘ (T_PUBLIC), expecting end of file in C:\ProgramData\Symcon\scripts\56653.ips.php on line 41
Abort Processing during Fatal-Error: syntax error, unexpected ‚public‘ (T_PUBLIC), expecting end of file
Error in Script C:\ProgramData\Symcon\scripts\56653.ips.php on Line 41

Wie bekomme ich den Requestring „downloadrequest“ unter, der an die URL gesendet wird um das von der URL empfangene File zu definieren ?
Das vorgeschlagene Script lädt ja „nur“ kommentarlos die in der URL angegebene Datei herunter.

hat keiner eine Idee, wo der Fehler herkommt bzw wie das Problem zu lösen wäre ?
Ich komme da nicht weiter :confused:

Hallo,

ich verwendet diesen Code in einem meiner Module:


function load_largefile($basename, $postfix)
{
    $tmpfile = $basename . '.tmp';

    $fp = fopen($tmpfile, 'w');
    if ($fp == false) {
        $this->SendDebug(__FUNCTION__, 'unabloe to open file "' . $tmpfile . '"', 0);
        return false;
    }

    $time_start = microtime(true);
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 120);
    curl_setopt($ch, CURLOPT_FILE, $fp);
    $cdata = curl_exec($ch);
    $cerrno = curl_errno($ch);
    $cerror = $cerrno ? curl_error($ch) : '';
    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $duration = round(microtime(true) - $time_start, 2);
    $this->SendDebug(__FUNCTION__, ' => errno=' . $cerrno . ', httpcode=' . $httpcode . ', duration=' . $duration . 's', 0);
    $this->SendDebug(__FUNCTION__, '    cdata=' . $cdata, 0);

    if (fclose($fp) == false) {
        $this->SendDebug(__FUNCTION__, 'unable to close file', 0);
        return false;
    }

    if ($cerrno || $httpcode != 200) {
        if (unlink($tmpfile) == false) {
            $this->SendDebug(__FUNCTION__, 'unable to delete file "' . $tmpfile . '"', 0);
        }
        return false;
    }

    $filename = $basename . $postfix;
    if (file_exists($filename) && unlink($filename) == false) {
        $this->SendDebug(__FUNCTION__, 'unable to delete file "' . $filename . '"', 0);
        return false;
    }
    if (rename($tmpfile, $filename) == false) {
        $this->SendDebug(__FUNCTION__, 'unable to rename file "' . $tmpfile . '" to "' . $filename . '"', 0);
        return false;
    }
    $stat = stat($filename);
    if ($stat == false) {
        $this->SendDebug(__FUNCTION__, 'unable to stat file "' . $filename . '"', 0);
        return false;
    }

    $size = floor($stat['size'] / (1024 * 1024) * 10) / 10;
    $this->SendDebug(__FUNCTION__, 'filename=' . $filename . ', size=' . $size . 'MB', 0);

    return true;
}

basename gibt den Speicherort der Datei an, jedoch ohne Postfix, der lautet erst ‚.tmp‘ und wird nach Gelingen des Downloads auf die Endung $postfix umbenannt.
Ist natürlich Error-Handling drin, das man sich sparen kann, aber in einem Modul sollte das schon sauber sein.

Achtung: das SendDebug entsprechend ersetzen durch IPS_LogMessage() oder echo

Gruß
demel

Magst du mal folgendes simples testen:

file_put_contents("/home/cams/aufnahmen/test.txt", "TESTTEST!");

Das solle, wenn du den Pfad sauber im Container gemappt hast, problemlos gehen.

Probiere ich bei Gelegenheit nochmal aus.
Ich kann mich aber erinnern dass auch ein Problem war, die doch teilweise sehr grossen Videodateien auszulesen, da der Puffer nicht gross genug war.
Kleine Dateien zu schreiben ging soweit, das wars aber.