Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > HTML, Javascript y otros
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 09-05-2006
Migue Rguez Migue Rguez is offline
Miembro
 
Registrado: May 2003
Ubicación: Sanlúcar de Bda. (Cádiz)
Posts: 10
Poder: 0
Migue Rguez Va por buen camino
subir determinado archivo

Que tal foro. En Delphi ando suelto, pero en html no se me pueden pedir grandes cosas.

Seguro que cualquiera que visite este post puede ayudarme: el caso es que necesito enviar un archivo al servidor pero el típico caso del formulario con el botón Examinar y Submit pues no me sirve. El archivo a enviar debe estar especificado en el mismo HTML. Es decir, al usuario no se le da la opción de escoger el archivo "file.txt" y pulsar submit sino que directamente es subido.

Tal vez no sea posible por el riesgo de seguridad que entrañaría esto, visitar una pagina web y empezar a subirse archivos de nuestro pc, pero nunca se sabe.

¿De qué manera puede hacerse?

Saludos y gracias de antemano.
Responder Con Cita
  #2  
Antiguo 09-05-2006
[kayetano] kayetano is offline
Miembro Premium
 
Registrado: May 2003
Ubicación: Elche
Posts: 644
Poder: 16
kayetano Va por buen camino
Hola

En primer lugar necesitas alguna lenguaje tipo PHP, ASP o JSP.
Sobre el tema de no permitir el indicar una ruta al usuario creo que factible, el problema reside en si ese archivo esta en otra ruta.
__________________
Salu2
KAYETANO

Cómo hacer preguntas de manera inteligente
Responder Con Cita
  #3  
Antiguo 10-05-2006
Migue Rguez Migue Rguez is offline
Miembro
 
Registrado: May 2003
Ubicación: Sanlúcar de Bda. (Cádiz)
Posts: 10
Poder: 0
Migue Rguez Va por buen camino
Kayetano gracias,

el archivo lo subo perfectamente al servidor mediante el formulario HTML pero es un poco tedioso y poco funcional el hecho de que los usuarios tengan que usar el dichoso formulario web.

Me explico mejor:
El servidor me recoge el archivo mediante un HTML parecido a esto...
Código PHP:
<FORM action=http://server.com/process
       
enctype="multipart/form-data"
       
method="post">
   <
P>
   
Cuál es tu nombre? <INPUT type="text" name="nameperson"><BR>
   
File to send? <INPUT type="file" name="file_name"><BR>
   <
INPUT type="submit" value="send"> <INPUT type="reset">
 </
FORM
desde mi aplicación en Delphi conozco el archivo, tamaño, path incluso el contenido del archivo puesto que el usuario asi se lo ha indicado a la aplicación.

La única manera que conozco es incrustar un TWebBrowser abriendo ese triste form y haciendo que el usuario seleccione el archivo.

Un poco enrevesado para un usuario de a pie no? Y más aún si queremos dotar a la aplicacion la propiedad de hacer drag&drop de uno o varios archivos desde el explorador de windows a la aplicación.

También intenté "capturar" el resultado del form donde me devolvía algo parecido a esto...
Código PHP:
--AaB03x
   Content
-Dispositionform-dataname="nameperson"

   
Migue
   
--AaB03x
   Content
-Dispositionform-dataname="file_name"filename="file1.txt"
   
Content-Typetext/plain

   
... contenido del archivo file1.txt ...
   
blablabla...
   --
AaB03x-- 
y pasárselo con el componente Indy IdHTTP1.Post(). Evidentemente no funciona y está claro que no debe ser la forma, pero como programador Delphi y aventurero tenía que probar.

Quizás alguien tenga la forma y pueda darme las directivas para hacerlo.

Gracias.
Responder Con Cita
  #4  
Antiguo 10-05-2006
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: Feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 18
seoane Va por buen camino
Entiendo que lo que quieres es mandar un archivo a un servidor web desde una aplicacion de delphi. Pero me surge la pregunta de quien sera el encargado de recibirlo, me explico, es muy sencillo mandar el contendio del archivo utilizando el metodo post, pero tal cual sin utilizar el formato que usan los navegadores para hacerlo ("multipart/form-data"), pero si del lado del servidor el encargado de recibir el archivo es un cgi creado por nosotros no deberia de haber problema para que entendiera lo que estamos mandando.

Pongamos un poco de codigo:
Código Delphi [-]
uses  WinInet;

function SubirArchivo(Servidor, Cgi, Archivo: string; Puerto: Word): Boolean;
var
  hNet: HINTERNET;
  hCon: HINTERNET;
  hReq: HINTERNET;
  Context: DWORD;
  Mem: TMemoryStream;
begin
  Context:= 0;
  Result := FALSE; 
  hNet := InternetOpen('Agente', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if (hNet <> nil) then
  begin
    hCon:= InternetConnect(hNet,PChar(Servidor),Puerto,nil,nil,INTERNET_SERVICE_HTTP,0,Context);
    if (hCon <> nil) then
    begin
      hReq:= HttpOpenRequest(hCon,'POST',PChar(Cgi),nil,nil,nil,
        INTERNET_FLAG_RELOAD,Context);
      if (hReq <> nil) then
      begin
        Mem:= TMemoryStream.Create;
        try
          try
            Mem.LoadFromFile(Archivo);
            HttpSendRequest(hReq,nil,0,Mem.Memory,Mem.Size);
          except end;
        finally
          Mem.Free;
        end;
        InternetCloseHandle(hReq);
      end;
      InternetCloseHandle(hCon);
    end;
    InternetCloseHandle(hNet);
  end;
end;

El metodo que describo aqui arriba mandaria los datos tal cual, sin codificarlos ni tratarlos de ninguna manera. Asi que del lado del servidor deberiamos de tener un cgi que supiera como le estamos mandando los datos y que supìera interpretarlo.

Aqui te propongo una solucion, habria que modificarla un poco segun tus necesidades, pero te puede dar una idea. Es un cgi, lo he probado en un servidor apache y me funciona bien:

Código Delphi [-]
program Upload;

uses
  Windows,
  Sysutils;

function Decode(s: string): string;
var
  i: integer;
  Ch: integer;
begin
  result := '';
  i := 1;
  while i <= Length(s) do
  begin
    if copy(s, i, 1) = '%' then
    begin
      Ch := StrToIntDef('$' + copy(s, i + 1, 2), -1);
      if (Ch > 0) and (Ch < 256) then
        result := result + Char(Ch);
      inc(i, 2);
    end
    else
      result := result + copy(s, i, 1);
    inc(i);
  end;
end;

function StdWrite(Output: THandle; Str: string): boolean;
var
  Escritos: Cardinal;
begin
  if WriteFile(Output,PChar(Str)^,Length(Str),Escritos,nil) then
    Result:= Escritos <> Cardinal(Length(Str))
  else Result:= FALSE;
end;

function StdWriteln(Output: THandle; Str: string): boolean;
begin
  Result:= StdWrite(Output,Str+#13#10);
end;

function GetEnvVar(Nombre: string): string;
var
  Str: PChar;
  Len: Integer;
begin
  Len:= GetEnvironmentVariable(PChar(Nombre),nil,0);
  if Len > 0 then
  begin
    GetMem(Str,Len+1);
    try
      GetEnvironmentVariable(PChar(Nombre),Str,Len);
      Result:= String(Str);
    finally
      FreeMem(Str);
    end;
  end else Result:= '';
end;

function Guardar(Input: THandle; Archivo: string): boolean;
var
  hFile: THandle;
  Leidos, Escritos, Total: Cardinal;
  Buffer: array[0..1024] of Byte;
  Root: string;
begin
  Total:= StrToIntDef(GetEnvVar('CONTENT_LENGTH'),0);
  if Total > 0 then
  begin
    // Aqui colocamos el directorio donde se colocaran los archivos recibidos
    Root:= 'C:\';
    Archivo:= ExpandFileName(Root+Archivo);
    if StrLIComp(PChar(Root),PChar(Archivo),Length(Root))=0 then
    begin
      hFile:= CreateFile(PChar(Archivo),GENERIC_WRITE,0,nil,CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,0);
      if hFile <> INVALID_HANDLE_VALUE then
      begin
        repeat
          if not ReadFile(Input, Buffer, sizeof(Buffer), Leidos, nil) then
            break;
          if not WriteFile(hFile,Buffer,Leidos,Escritos,nil) then
            break;
          Dec(Total,Leidos);
        until (Leidos = 0) or (Total = 0);
        CloseHandle(hFile);
      end;
    end;
    Result:= Total = 0;
  end else Result:= TRUE;
end;

procedure Vamos;
var
  Output: THandle;
  Input: THandle;
  QueryString: string;
begin
  Output:= GetStdHandle(STD_OUTPUT_HANDLE);
  Input:= GetStdHandle(STD_INPUT_HANDLE);
  if (Output <> INVALID_HANDLE_VALUE) and (Input <> INVALID_HANDLE_VALUE) then
  begin
    QueryString:= Decode(GetEnvVar('QUERY_STRING'));
    StdWriteln(Output,'Content-type: text/html');
    StdWriteln(Output,'');
    if Guardar(Input,QueryString) then
      StdWriteln(Output,'OK')
    else
      StdWriteln(Output,'ERROR');
  end;
end;

begin
  Vamos;
end.

Y por ultimo solo nos queda utilizar la primera funcion para mandar el archivo, de esta manera:
Código Delphi [-]
SubirArchivo('www.tuservidor.com','/cgi-bin/upload.exe?archivo.txt','archivo.txt',80);

Espero que te sirva, aunque si lo que necesitas es subirlo con formato, pues viene siendo lo mismo pero dandole formato a los datos antes de mandarlos.
Responder Con Cita
  #5  
Antiguo 13-05-2006
Migue Rguez Migue Rguez is offline
Miembro
 
Registrado: May 2003
Ubicación: Sanlúcar de Bda. (Cádiz)
Posts: 10
Poder: 0
Migue Rguez Va por buen camino
Gracias seoane!

Sencillamente magistral tu respuesta, es para apuntarla y no olvidarla. Ahora bien, no solucionó mi problema pero consiguió abrirme la mente y obtuve la forma de darle salida a este caso.

Os lo explico para compartirlo con todos vosotros. Prefiero dejar la idea antes que el código ya que cada caso puede ser particular.

La idea principal es hacer un POST conteniendo la respuesta que envía nuestro navegador del formulario HTML. Es decir, qué cosa recibe el servidor para que termine recibiendo perfectamente lo que le enviamos. Para esto puedes usar un programa gratuito de http://www.softx.org/internet-logger.html que logea todo el tráfico web cliente-servidor-servidor-cliente.

Analizamos el log resultante y extraemos toda la respuesta que devuelve el navegador.

Con esta respuesta la dividimos en dos partes: la primera que va desde el principio del log extraido hasta la primera posicion donde comienza el envio del contenido del archivo a enviar por el formulario web. Y la segunda parte que va desde la ultima posicion del archivo a enviar hasta el final. Con lo que el resultante de esta operación son dos archivos txt (si asi queremos guardarlo) sin el contenido del archivo a enviar.

Ahora sólo queda sustituir en ambas partes la información que nos interese tales como el nombre de archivo, el tamaño, la ubicación, y otros datos que se incluyen en el formulario web.

A continuación se carga en un TStreamMemory (SM1) la primera parte, en otro TStreamMemory (SM2) el contenido del archivo (SM2.LoadFromFile(archivo) y en el ultimo (SM3) la última parte del log.

Se concatenan los tres TStreamMemory.

Se prepara la cabecera del TidHTTP en base al log que registramos (idhttp1.Request.Connection, IdHTTP1.Request.ContentType, etc...) y finalmente se envían con TidHTTP.Post()

El resultado es satisfactorio al menos en mi caso. Es un procedimiento un poco enrevesado pero al menos puede ayudarnos a sacarnos del atasco cuando no sabemos que script posee el servidor ni sabemos de que manera procesa la información que le enviamos.

Saludos y espero que esto saque a más de uno de un aprieto.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Encontrar un registro determinado. alfredosg19 Conexión con bases de datos 3 20-06-2005 21:09:49
que programa esta ejecutando un determinado archivo slat API de Windows 1 11-04-2005 17:11:23
Saber que executable usa un puerto determinado... StartKill API de Windows 2 06-08-2004 11:34:54
Subir Archivo Plano agora18 Conexión con bases de datos 3 16-09-2003 16:25:30
Abrir un fichero determinado en Word Tonio Varios 2 26-08-2003 17:35:46


La franja horaria es GMT +2. Ahora son las 10:01:57.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi