Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: advAJAX i przesyłanie plików
Forum PHP.pl > Forum > XML, AJAX
Edric
Witam.
Staram się w swoim projekcie zastosować przesyłanie plików na serwer bez przeładowywania strony. Chciałem do tego wykorzystać bibliotekę advAJAX. Kod na którym eksperymentuje, wygląda następująco:

formularz.html:
  1. <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
  2. <script type="text/javascript" src="advajax.js"></script>
  3.  
  4. <script type="text/javascript">
  5.  
  6. window.onload = przeslij;
  7.  
  8. function przeslij()
  9. {
  10. advAJAX.assign(document.getElementById("form_1"), {
  11. onSuccess : function(obj) {
  12. document.getElementById("info").innerHTML = obj.responseText;
  13. }
  14. });
  15. }
  16. </head>
  17.  
  18.  
  19. <form method="post" enctype="multipart/form-data" action="plik.php" id="form_1">
  20. Plik:<br />
  21. <input type="file" name="nazwa" /><br />
  22. <input type="submit" value="OK" />
  23. </form>
  24.  
  25. <span id="info" style="display: block"></span>
  26.  
  27. </body>
  28. </html>


plik.php:
  1. <?
  2. var_dump($_FILES);
  3. ?>



Wywołanie window.onload = przeslij; sprawia, że obsługę formularza przejmuje advAJAX. Gdy wywołanie to jest aktywne, to jako odpowiedź otrzymuję: "array(0) { }",
czyli php nie stwierdziło żadnych plików do przesłania. Gdy wywołanie window.onload = przeslij; usuwam, formularz obsługiwany jest standardowo i po otwarciu nowej strony mam:

array(1) { ["username"]=> array(5) { ["name"]=> string(15) "Clipboard01.jpg" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(74) "C:\Documents and Settings\Edric\Ustawienia lokalne\Temp\php218.tmp" ["error"]=> int(0) ["size"]=> int(250548) }

czyli formularz działa prawidłowo. Wygląda na to, że advAJAX nie potrafi obsługiwać przesyłania plików.. albo ja robie coś źle. I tu pytanie - co zrobić żeby to zadziałało? Dodam jeszcze, że jeśli zmienię typ input na 'text', i sprawdzę zmienną $_POST po przesłaniu za pomocą advAJAX to wszystko działa dobrze.

Może zna ktoś jakiś inny obiekt AJAX, który pomógłby mi to zrealizować?

Próbowałem problem rozwiązać w inny sposób, ale na drodze stanęła mi Opera i jej obsługa inputów dla plików (pytanie na ten temat również znajduje się na forum.

Bardzo proszę o pomoc, bo naprawdę nie wiem jak ten problem rozwiązać.

Niestety nie wiem, jak to wygląda z advAJAX, ale znalazłem coś co prawdopodobnie rozwiązuje ten problem:

http://en.dklab.ru/lib/JsHttpRequest/" title="Zobacz w manualu PHP" target="_manual
sowiq
NIestety, ale AJAX jak i cała JavaScript nie obsługuje przesyłania plików. Jeśli zależy Ci na przesyłaniu formularza z plikiem bez przeładowania strony, musisz zastosować ukrytą ramkę (np 1px x 1px) i do niej normalnie submitować formularz.
simple programmer
Nie działa, bo w ten sposób normalnie mógłbyś przeglądać sobie kompa użytkownika, a tego byś jako przeglądający przecież nie chciał.
Edric
Cytat(sowiq @ 10.06.2008, 18:28:56 ) *
NIestety, ale AJAX jak i cała JavaScript nie obsługuje przesyłania plików. Jeśli zależy Ci na przesyłaniu formularza z plikiem bez przeładowania strony, musisz zastosować ukrytą ramkę (np 1px x 1px) i do niej normalnie submitować formularz.


Ajax czy też JS jako taki nie. Ale jak widać w moim przykładowym kodzie, AJAX potrafi wywoływać asynchroniczie kod PHP, który wysyłaniem plików spokojnie może się zająć (do tego ma przecież zmienną $_FILES). No i istnieje coś takiego jak <input type='file'/> co pozwala na pobranie nazwy pliku z dysku lokalnego za pomocą przeglądarki. Problem tkwił w tym, że biblioteka, z której korzystałem (advAJAX) akurat z przesyłaniem plików sobie nie radzi. Niemniej znalazłem bibliotekę która to umożliwia - http://en.dklab.ru/lib/JsHttpRequest . Jak znajdę chwilę czasu to wrzucę tu kod pozwalający z jej pomocą na kopiowanie plików na serwer bez przeładowywania strony i bez ukrytych ramek.

Cytat(simple programmer @ 10.06.2008, 19:38:40 ) *
Nie działa, bo w ten sposób normalnie mógłbyś przeglądać sobie kompa użytkownika, a tego byś jako przeglądający przecież nie chciał.


Niestety nie rozumiem... Kod który piszę, ma pozwalać na przesłanie pliku z dysku lokalnego na serwer, bez przeładowania strony. Przeglądanie własnego dysku, to chyba nie problem - umożliwia to input z type='file'.
wlamywacz
Nie zrobisz tego w ten sposób po prostu - względy bezpieczeństwa. Jedyna opcja to perl itp.

P.S. Słyszałem że ustawiając specjalnie FF można to wykonać ale to jak robisz tylko dla siebie.
Edric
Cytat(wlamywacz @ 12.06.2008, 23:07:20 ) *
Nie zrobisz tego w ten sposób po prostu - względy bezpieczeństwa. Jedyna opcja to perl itp.

P.S. Słyszałem że ustawiając specjalnie FF można to wykonać ale to jak robisz tylko dla siebie.


Ale czemu względy bezpieczeństwa? Przecież przesyłanie plików na serwer to normalna sprawa - po to jest input type=file, po to jest m.in. POST, po to jest zmienna $_FILES w PHP. Jedyne co ja chcę zmienić, to wysyłać te pliki bez przeładowania strony.

Zresztą - działa mi to. Poniżej wrzucam kod dla pliku html oraz php. W html są tylko najważniejsze rzeczy - skrypt i formularz. <body> itp sobie darowałem;).

user.html:
  1. <script src="JsHttpRequest.js"></script>
  2. <script type="text/javascript" language="JavaScript">
  3. function doLoad(value) {
  4. // Create new JsHttpRequest object.
  5. var req = new JsHttpRequest();
  6. // Code automatically called on load finishing.
  7. req.onreadystatechange = function() {
  8. if (req.readyState == 4) {
  9. // Write result to page element (_RESULT becomes responseJS).
  10. document.getElementById('result').innerHTML =
  11. '<b>MD5("'+req.responseJS.q+'")</b> = ' +
  12. '"' + req.responseJS.md5 + '"<br> ';
  13. // Write debug information too (output becomes responseText).
  14. document.getElementById('debug').innerHTML = req.responseText;
  15. }
  16. }
  17. // Prepare request object (automatically choose GET or POST).
  18. req.open(null, 'serw.php', true);
  19. // Send data to backend.
  20. req.send( { q: value } );
  21. }
  22.  
  23. <!-- Please note that we must specify enctype to multipart/form-data! -->
  24. <form method="post" enctype="multipart/form-data" onsubmit="return false">
  25. File: <input type="file" name="upl">
  26. <input type="button" value="Wyślij"
  27. onclick="doLoad(this.form.upl)">
  28. </form>
  29.  
  30. <div id="result" style="border:1px solid #000; padding:2px">
  31. Structured results
  32. </div>
  33. <div id="debug" style="border:1px dashed red; padding:2px">
  34. Debug info
  35. </div>


serw.php
  1. <?php
  2. // Load JsHttpRequest backend.
  3. require_once "JsHttpRequest.php";
  4. // Create main library object. You MUST specify page encoding!
  5. $JsHttpRequest =& new JsHttpRequest("UTF-8");
  6. // Store resulting data in $_RESULT array (will appear in req.responseJs).
  7. $GLOBALS['_RESULT'] = array(
  8. "q"  => 'file ' . $_FILES['q']['name'],
  9. "md5"  => md5(@file_get_contents($_FILES['q']['tmp_name'])),
  10. ); 
  11.  
  12. $file= $_FILES['q']['tmp_name'];
  13. $zapisz_jako = $_FILES["q"]["name"];
  14. copy($file, $zapisz_jako);
  15.  
  16. // Below is unparsed stream data (will appear in req.responseText).
  17. ?>
  18. <pre>
  19. <b>Uploaded files:</b> <?=print_r($_FILES, 1)?>
  20. </pre>


Oczywiście wymagane są pliki JsHttpRequest.js oraz JsHttpRequest.php - wszystko na stronie http://en.dklab.ru/lib/JsHttpRequest/

Mi całość działa w Operze, FF i IE7. W FF nie włączałem żadnych specjalnych opcji - lecę na standardowych ustawieniach.
protheo
Cytat(Edric @ 11.06.2008, 12:17:43 ) *
Ajax czy też JS jako taki nie. Ale jak widać w moim przykładowym kodzie, AJAX potrafi wywoływać asynchroniczie kod PHP, który wysyłaniem plików spokojnie może się zająć (do tego ma przecież zmienną $_FILES). No i istnieje coś takiego jak <input type='file'/> co pozwala na pobranie nazwy pliku z dysku lokalnego za pomocą przeglądarki. Problem tkwił w tym, że biblioteka, z której korzystałem (advAJAX) akurat z przesyłaniem plików sobie nie radzi. Niemniej znalazłem bibliotekę która to umożliwia - http://en.dklab.ru/lib/JsHttpRequest . Jak znajdę chwilę czasu to wrzucę tu kod pozwalający z jej pomocą na kopiowanie plików na serwer bez przeładowywania strony i bez ukrytych ramek.



Niestety nie rozumiem... Kod który piszę, ma pozwalać na przesłanie pliku z dysku lokalnego na serwer, bez przeładowania strony. Przeglądanie własnego dysku, to chyba nie problem - umożliwia to input z type='file'.



Widzisz i tu właśnie się mylisz gdybyś przeczytał specyfikację i zaglądnął do kodu z pliku, który podajesz niżej czyli: JsHttpRequest.js, to zobaczyłbyś że tak naprawdę ta biblioteka działa na zasadzie automatycznego wyboru rozwiązania uploadu dla przesyłanych danych. W przpadku plików tworzone jest rozwiązanie w oparciu właśnie o iframe: "Automatic choice of the best AJAX realization (XMLHttpRequest, <script>, <IFRAME>)."

Tak jak pisali wszyscy powyżej niestety nie ma możliwości załadować pliku za pomocą JavaScript, naprawdę długo szukałem takiego rozwiązania.

Wracając do JSHttpRequest i IFRAME poniżej fragmenty z pliku JSHttpRequest.js:

" * This library tries to use XMLHttpRequest (if available), and on
* failure - use dynamically created <script> elements. Backend code
* is the same for both cases. Library also supports file uploading;
* in this case it uses FORM+IFRAME-based loading."
.
.
.

" // Create invisible IFRAME with temporary form (form is used on empty queryElem).
var div = document.createElement('DIV');

var ifname = 'jshr_i_' + id;
"

Z tego co udało mi się ustalić (a i pewnie i to nie jest do końca takie pewne) to są 4 sposoby przesyłania plików bez przeładowania strony:

1. swfupload - czyli upload realizowany z poziomu flasha (podobno nie działa w 10 wersji flash - ale tego nie sprawdzałem),

2. form+ifrme - w sumie kilka sposobów realizacji ale idea generalnie taka sama - form ładowany do iframe,

3. jQuery - tu nie jestem pewien bo to teoretycznie biblioteka JavaScript więc niby też powinien być iframe ale w to się nie zagłębiałem.,

4. Przeładowanie całej strony po uploadzie (pokaz miniatury wykonuje skrypt php w oparciu o zmienne sesji lub zmienne JavaScript, który generuje pierwotny form do wprowadzania danych).

Jeżeli są jakieś inne rozwiązania bardzo chętnie je poznam i na ich temat porozmawiam smile.gif w razie czego proszę na priv.

Pozdrawiam

To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.