Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it L'avatar di quincy
    Registrato dal
    Aug 2003
    Messaggi
    247

    [CGI] c forzare download

    Salve a tutti,

    volevo forzare il download di un file (.txt) da parte del browser che fà richiesta tramite get con un mio CGI scritto in C.Ho trovato gli header per fare questo ma il file non mi si scarica correttamente.Provo a fare un esempio. L'utente preme su un bottone per recuperare un file .txt e questo bottone apre un get ad un mio cgi di nome example.exe e mi passa come parametro di query get il nome del file.
    Io recupero il nome inviatomi e al browser mando questi header:
    fprintf(cgiOut, "Content-type: %s\r\n\r\n", "application/x-download");
    fprintf(cgiOut, "Content-Disposition: attachment; filename=%s;\r\n\r\n", "prova.txt");
    fprintf(cgiOut, "Accept-Ranges: bytes\r\n\r\n");
    fprintf(cgiOut, "Content-Length: %d\r\n\r\n",70);
    if( (stream = fopen( path, "rt" )) != NULL )
    {
    while( !feof( stream ) )
    {
    //leggo tutti i BYTE in una volta solo
    numByte = fread( buffer, sizeof( char ), 500, stream );
    buffer[70] = '\0';
    fprintf(cgiOut,buffer);
    if( ferror( stream ) )
    return 0;
    }
    }
    fclose( stream );
    Il cgiOut sarebbe l'invio al browser della stringa.
    Il fatto è che il browser si rende conto che deve essere scaricato un file(mi pare la finestra di download file) indice che il content-type è stato letto ma il nome del file è example.exe(ossia quello del CGI) e mi restituisce gli altri header come stringa. La prova l'ho fatto con un file di 70 bytes.

    Qualche idea o suggerimento?
    Andrea

  2. #2
    Non conosco abbastanza il C da poterti aiutare.
    Guarda se quasto codice Perl commentato ti può aiutare.

    codice:
    #!/usr/bin/perl 
    
    use strict; # Ormai oggi è quasi obbligatorio.
    use CGI; # semplifica la lettura dell'input
    
    my $dir = "/var/www/html"; # directory che contiene i file da scaricare
    
    my $q = new CGI; 
    
    my $file = $q->param('file'); # raccoglie il nome file
    
    my $size = (-s "$dir/$file"); # ne calcola la dimensione
    
    my $buf;
    
    # segue l'header http necessario per impedire l'apertura
    # del file
    print "Content-type: octet/stream\n"; 
    print "Content-length: $size\n";
    print "Content-disposition: attachment; filename=$dir/$file\n\n";
    
    open (FILE, "<$dir/$file");
    # il file viene letto e poi scritto sullo STOUT
    # differenziando i file binari da quelli ASCII
    if (-B "$dir/$file") {
    binmode FILE;
    while (read FILE, $buf, 1024) {
    print $buf;
    }
    } else {
    while (<FILE> ) {
    print;
    }
    }
    close FILE;
    
    exit;
    Marco Allegretti
    shishii@tiscalinet.it
    Lang: PERL, PHP, SQL.
    Linux user n° 268623 Fedora Core 10, Fedora Core 6, Debian Sarge on mips

  3. #3
    Utente di HTML.it L'avatar di quincy
    Registrato dal
    Aug 2003
    Messaggi
    247
    Grazie mille per la tua risposta!
    Proverò ad adattare il tuo codice e se riesco posto il codice in C!


    Ciao
    Andrea

  4. #4
    Moderatore di Sicurezza informatica e virus L'avatar di Habanero
    Registrato dal
    Jun 2001
    Messaggi
    9,782
    il problema è semplicemente che devi mandare il doppio invio a capo "\r\n\r\n" solo dopo l'ultima riga dell'header non ad ogni riga.... il doppio invio a capo indica la separazione tra header e contenuto...
    Prova così:

    codice:
    fprintf(cgiOut, "Content-type: %s\r\n", "application/x-download");
    fprintf(cgiOut, "Content-Disposition: attachment; filename=%s;\r\n", "prova.txt");
    fprintf(cgiOut, "Accept-Ranges: bytes\r\n");
    fprintf(cgiOut, "Content-Length: %d\r\n\r\n",70);
    if( (stream = fopen( path, "rt" )) != NULL )
    {
    while( !feof( stream ) )
    {
    //leggo tutti i BYTE in una volta solo
    numByte = fread( buffer, sizeof( char ), 500, stream );
    buffer[70] = '\0';
    fprintf(cgiOut,buffer);
    if( ferror( stream ) )
    return 0;
    }
    }
    fclose( stream );
    Leggi il REGOLAMENTO!

    E' molto complicato, un mucchio di input e output, una quantità di informazioni, un mucchio di elementi da considerare, ho una quantità di elementi da tener presente...
    Drugo

  5. #5
    Utente di HTML.it L'avatar di quincy
    Registrato dal
    Aug 2003
    Messaggi
    247
    Grazie per la risposta!

    In effetti era come scrivevi.
    Ora però ho un altro problema. Il numero dei byte del file da inviare li leggo con la funzione stat, il contenuto lo leggo con fread. Il fatto è che la size del file che mi indica la stat differisce dal numero di byte letti dalla fread,ossia me ne legge di meno la fread!
    Mi sapresti spiegare perchè?
    Fai conto che il byte da inviare è semplicemente un documento formattato con dei numeri e dei \t o \n(insomma una tabella di dati).

    Ti ringrazio per il tuo aiuto.
    Andrea

  6. #6
    Utente di HTML.it L'avatar di quincy
    Registrato dal
    Aug 2003
    Messaggi
    247
    OK scoperto l'arcano!

    Per fare il punto della cosa,gli header sono quelli scritti da Habanero. Quando però deve essere letto il file da inviare, la modalità di lettura deve essere binaria, in maniera tale che le sostituzioni dei \n\r vengono soppresse, quindi i file viene letto per intero.

    Grazie ad entrambi per l'aiuto fornitomi.

    Alla prossima.
    Andrea

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.