Avatar billede reffak Nybegynder
03. juni 2002 - 20:41 Der er 21 kommentarer og
2 løsninger

fil download

Hej

Jeg håber I kan hjælpe mig med følgende problem.

Jeg ønsker at kunne:
-Downloade en fil fra en asp.net side
-Spærre adgangen til samme fil, hvis denne tilgås direkte.

Det skal altså kun være muligt at downloade filen, igennem asp.net siden. Selv hvis man kendte den fulde sti til filen, skulle det ikke være muligt at hente den direkte.

Serveren og dens opsætning kan tilpasses løsningen.

Jeg har stillet mange point på højkant - og forventer derfor mere end blot links eller gode forslag. Points bliver givet til den første løsning der virker.

MVH
Avatar billede odegaard Nybegynder
04. juni 2002 - 00:03 #1
Dette eksempel skulle kunne gøre det du ønsker. Håber det kan bruges.
Du skal selvfølgelig angive filnavnet mere dynamisk, hvis den fil der skal downloades, skal baseres på et valg fra brugeren. Husk: Hvis filen ikke ligger i dit web-bibliotek, at 'computernavn\ASPNET' skal have læseadgang til filen !
Ved content-disposition kan du i øvrigt selv angive et filnavn som klienten skal tro filen hedder. I dette eksempel benyttes dog filens eget filnavn.
-------------sendfile.aspx--------------------
<%@ import namespace="System.IO" %>
<script language="VB" runat="Server">

Sub Page_Load(Source As Object, E As EventArgs)

  ' vælg sti til fil-download og opret FileInfo for at læse properties
  Dim path as string = "C:\minfil.zip"
  Dim file as System.IO.FileInfo  = new System.IO.FileInfo(path)

  ' slet alt output fra bufferen
  Response.Clear()
  ' tilføj header, der kalder den almindelige standard
  ' header som vise Download/SaveAs dialogen
  Response.AddHeader("Content-Disposition", "filename=" + file.Name)

  ' Tilføj header der angiver filstørrelse
  ' så browseren kan vise download-detaljer
  Response.AddHeader("Content-Length", file.Length.ToString())

  ' Angiv at dette er en stream som ikke kan læses af klienten
  ' og derfor skal downloades
  Response.ContentType = "application/octet-stream"

  ' Send fil-strømmen til klienten
  Response.WriteFile(file.FullName)

  ' Stop eksekvering af siden
  Response.End()
 
End Sub

</SCRIPT>
Avatar billede odegaard Nybegynder
04. juni 2002 - 00:06 #2
Forresten, nu du sætter så mange penge på højkant, kan du da også få den i C-sharp :-)
------------------------------------------------
private void Page_Load(object sender, System.EventArgs e)
{
string path = "C:\\minfil.zip";
System.IO.FileInfo file = new System.IO.FileInfo(path);
Response.Clear();
Response.AddHeader("Content-Disposition", "filename=" + file.Name);
Response.AddHeader("Content-Length", file.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(file.FullName);
Response.End();
}
Avatar billede reffak Nybegynder
04. juni 2002 - 02:25 #3
Odegaard > Det ser godt ud - jeg vil teste det senere i aften

MVH
Avatar billede jakobandersen Nybegynder
04. juni 2002 - 09:01 #4
Odegaard-> Du streamer da ikke andet end filens navn?

reffek>
Et eksempel på rigtig streaming af en fil kunne se sådan her ud:

<%@ Import Namespace="System.IO" %>
<script runat="server" language="c#">
void Page_Load(){
FileStream objFileStream= new FileStream(@"c:\dokumenter\foo.doc",
FileMode.Open);
int FilStorrelse = (int)objFileStream.Length;
byte[] Buffer = new byte[FilStorrelse];
objFileStream.Read(Buffer, 0, FilStorrelse);
objFileStream.Close();
Response.ContentType = "application/octet-stream";
Response.AddHeader( "content-disposition","filename=foo.doc");
Response.BinaryWrite(Buffer);
}
</script>
Avatar billede reffak Nybegynder
04. juni 2002 - 09:35 #5
til jer begge : Hvor har I fundet denne information?
Avatar billede jakobandersen Nybegynder
04. juni 2002 - 09:39 #6
I dokumentationen.
Avatar billede odegaard Nybegynder
04. juni 2002 - 12:32 #7
Moonduck-> Nej hovsa :-) Jeg kan godt se at jeg lige fuckede up til sidst :-)
Jeg tjekkede bare at koden returnerede en fil, men kan da godt se at den er lidt forkert i sidste linje :-)
Jeg kigger lige på det når jeg kommer hjem.

Du glemmer iøvrigt at angive filens størrelse. Det er meget rart at modtageren kan se hvor stor filen er, og hvor langt den nået i downloadning af filen.

Reffak: Kombination af SDK'en og et gammelt eksempel jeg bruger til returnering af dynamisk genererede filer.
Avatar billede reffak Nybegynder
04. juni 2002 - 18:00 #8
Jeg har afprøvet jeres løsninger.
Begge virker med det samme, hvilket jo er perfekt! Men:
I streamer en fil ind i hukommelsen, og downloader den derefter? Det er absolut ikke anvendeligt!. Jeg regner med at skulle håndtere filer på +50MB. Det er klart, at blot 2-3 brugere samtidig vil lægge systemet ned.

Jeg testede jeres løsninger med en 40MB fil, og fandt, at de begge krævede markant mere end 40MB RAM. Med Odegaards løsning blev denne hukommelse ikke frigivet efterfølgende, hvilket dog var delvist tilfældet med Moonducks - som desuden arbejdede en del hurtigere.

Grundlæggende er jeres løsninger dog ikke anvendelige. Jeg tror der skal tænkes i nye baner. Jeg ved der findes alternativer - bare ikke hvad :-).

Pointene er stadig på højkant. Hvis der er nogen der kan levere en løsning der er ressourcemæssig forsvarlig, gives pointene hertil. Hvis ikke der kommer andre løsninger i løbet af 7 dage, deler Odegaard og Moonduck pointene.

MVH
Avatar billede jakobandersen Nybegynder
04. juni 2002 - 18:14 #9
Jeg kan umiddelbart ikke se nogen løsning på dit problem eftersom ideen med en stream netop er at dataene indlæses i direkte i response streamen med memory som "mellemstation"

Alternativet er at lege med noget authentication hvor du åbner op for en given IP i x antal sekunder til at downloade filen direkte. Jeg har leget med denne løsningsmodel men det kræver en del editering i web.config on the fly
Avatar billede reffak Nybegynder
04. juni 2002 - 18:42 #10
Jeg tror du referer til Impersonation, som man - ganske rigtigt - kan sætte i web.config. Man kan dog godt udføre impersonation uden om web.config. Denne side forklarer hvordan :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconimpersonatingreverting.asp

Men, jeg har selv rodet en del med impersonation. Helt grundlæggende lader det ikke til at have effekt på ikke-aspx filer. Altså er det heller ikke anvendeligt.

Du henviser til noget IP. Det kender jeg ikke selv til.

Serveren kan - som jeg startede med at sige - tilpasses til løsningen. Serveren kører også en BulletProof FTP server, som evt. kan indgå i løsningen.

Og endelig : Jeg ved det kan lade sig gøre. Diverse sites anvender denne funktionalitet. Deriblandt fildelingen på DTU's Campusnet.

MVH
Avatar billede reffak Nybegynder
04. juni 2002 - 18:46 #11
NT Authentication (basic/digest/kerberos) er heller ikke umiddelbar ønskværdig. Brugere bag firewalls har tidligere meldt om problemer med denne løsning.
Avatar billede jakobandersen Nybegynder
04. juni 2002 - 19:17 #12
Jeg vil uden at vide gætte på at disse løsninger kører på unix platformen og gør brug af .htacess til at sørge for at kun brugere der har indtastet brugernavn og password kan bruges.

Jeg kender desværre ikke lige Bulletproof FTP Server..

Det trick med IP'en var min fejl, den implementation jeg lavede af dette involverede også streaming.

Hvis du ender med at bruge en stream så vil jeg anbefale dig at kigge på at lave en (web)handler (Jeg tror webhandler er et Beta2 fænomen) på denne måde sparer du lidt memory da Page objektet ikke bliver instansieret, kig evt. på:
http://samples.gotdotnet.com/quickstart/aspplus/doc/httphandlers.aspx
Avatar billede odegaard Nybegynder
04. juni 2002 - 23:30 #13
Moonduck: DTU's Campusnet kører på IIS5.0 med klassisk ASP (det er tilfældigvis lige noget jeg ved :-)

Reffak: Hvorfra ved du egentlig at andre ikke bruger streaming? Umiddelbart ligner det jo denne metode der benyttes.

Til jer andre: Man kan prøve en demo af campusnettet (som faktisk er meget blæret) her: http://cndemo.dtv.dk/
Avatar billede odegaard Nybegynder
04. juni 2002 - 23:34 #14
Moonduck: Forresten, nu jeg kigger nærmere efter i min kode, så er det da ikke et filnavn jeg streamer. Den er skam god nok. Det jeg streamer, er en fil, hvis navn og sti jeg angiver inden i writefile metoden (i dette tilfælde file.Fullname).
Du skulle vel ikke komme til at have læst det som response.writetext(file.Fullname) ?
Avatar billede jakobandersen Nybegynder
04. juni 2002 - 23:37 #15
odegaard> Jo, jeg så først nu at du brugte Response.WriteFile(), undskyld hvis jeg anklagede dig for noget :-)
Avatar billede odegaard Nybegynder
05. juni 2002 - 00:21 #16
Jeg kan dog godt se problemet med at returnerer en kæmpe fil (forsøgte lige med en 700mb fil og så lå systemet pludselig på 1gb benyttet ram).
"Response.BufferOutput=False" lyder lidt som løsningen, men det hjalp heller ikke.
Jeg har også forsøgt at læse dele af filen ind i en mindre buffer, og så efterhånden returnere data der bliver læst. Dette løste til dels RAM-problemet, men tilgengæld gik alting ufatteligt langsomt (downloadede stabilt 5 bytes/sek fra localhost). Men det kan godt være at dette kunne være en løsningsmulighed, hvis man kan optimere tingene lidt.
Avatar billede odegaard Nybegynder
05. juni 2002 - 00:33 #17
Prøv lige at erstatte response.writefile() i mit eksempel med følgende:
--------------
  Dim objFileStream As FileStream = new FileStream(path,FileMode.Open)
  Dim bufferlength as Integer = 1024*1024
  Dim Buff(bufferlength-1) as Byte
  Dim position as long = 0

  for position=0 to file.Length()-1 step bufferlength
      objFileStream.Read(Buff, 0, bufferlength)
      Response.binarywrite(Buff)
  next
  objFileStream.Close()
-------------------
Du skal i starten af koden ligeledes indsætte "response.bufferoutput=false".
Det bruger stadig meget RAM, men langt fra lige så meget som filens størrelse (ram bliver løbende frigivet igen allerede inden download er slut). Du kan evt. prøve at lege lidt med bufferlængden. Den har tilsyneladende betydning for RAM og downloadhastighed.
Avatar billede odegaard Nybegynder
05. juni 2002 - 00:35 #18
Hmm.... bufferlængden burde vel ikke kunne indeholde sådan et stort tal, når det er en integer, men det virker da :-)
Avatar billede jakobandersen Nybegynder
05. juni 2002 - 00:44 #19
I dit eksempel vil der stadig opstå problemer da tilgangen til memory sker så tit at du bruger mange ressourcer på at allokere og deallokkere konstant, så rent performancemæssigt tror jeg det er et fedt hvad du gør, men måske skulle man lige fyre op under WAST og tjekke nogle resulateter med lidt større load og flere simultane brugere, men det bliver ikke før imorgen på arbejde da jeg ikke kan lave den vilde multitrådede test med min laptop :-)
Avatar billede reffak Nybegynder
05. juni 2002 - 12:47 #20
Odegaard > Jeg har selv rodet med at køre med en begrænset buffer - at læse lidt, og derefter skrive lidt. Men det giver blot et andet problem : Det du sparer i RAM, taber du i CPU ressourcer. Processen bruger nu markant mindre RAM, men arbejder til gengæld meget længere med opgaven.

Det er grundlæggende en forkert tangent vi er løbet ud af her. Streaming er ikke vejen frem - ligegyldigt hvordan. Der skal tænkes i andre baner; man har brug for at intercepte kaldet til en fil, hvilket er muligt - men besværligt.

MVH
Avatar billede jakobandersen Nybegynder
05. juni 2002 - 13:01 #21
Du skal nok til at lege med et ISAPI filter som du sender alle dine filer igennem og validerer brugeren.
Avatar billede reffak Nybegynder
10. juni 2002 - 21:46 #22
Jeg lukker den her, med stor irritation.
moonduck > Ja, jeg har også rodet en del med ISAPI filtre. Og fik da også tingene til at virke, således at filen blev interceptet. Igen krævede løsningen dog enorme mængder RAM.

Jeg har også rodet med HttpHandlers, HttpModules og HttpApplications. Alle kom til at virke - og alle kostede det samme i RAM. Måske har I ret i, at det er sådan alle andre gør - det kan være at fildelingstjenester bare er enormt ressourcekrævende - men det virker skørt, at så simpel en proces skal koste så mange ressourcer.

Den endelige løsning blev en sammensmeltning mellem BulletProof FTP serveren og ASP.NET siderne: FTP protokollen leverer sikkerheden, og brugernes username/passwords opdateres igennem .ini filer. Besværligt, grimt, latterligt - pis. Men det virker, og koster ikke ressourcer.

I skal begge have tak for jeres indsats.

MVH
Avatar billede reffak Nybegynder
28. juni 2002 - 02:43 #23
SÅ fik jeg fred i sindet!

Den ultimative løsning er fundet. Jeg kan nu
-Downloade en fil fra en asp.net side
-Spærre adgangen til samme fil, hvis denne tilgås direkte.
-Sende 1 terabyte hvis jeg ville, og det koster INTET i RAM eller CPU ressourcer.

Problemet blev løst the hard way. Jeg har kodet min egen FTP Server, helt fra bunden. Ved hjælp af standard FTP kommandoer kan jeg håndtere brugeres FTP forespørgsler, styre hvem der skal have hvad, sende en tråd afsted når en bruger forespørger en fil, lukke tråden når filen er downloadet...alles.

Det tog godt nok også lang tid - men aahhh, hvor er det fedt, når noget endelig virker :-).

Igen, tak for jeres hjælp. Jeres ideer til Streaming var hvad der startede hele denne tankegang, så pointene er stadig givet godt ud.

MVH
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester