Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Форма для загрузки файла по ссылке (https://javascript.ru/forum/misc/72601-forma-dlya-zagruzki-fajjla-po-ssylke.html)

kupidon 11.02.2018 19:26

Форма для загрузки файла по ссылке
 
Всем доброго времени суток. Прошу помощи.
На странице редактирования товара интернет магазина есть две формы по загрузке фото к данному товару. Работать должна так: в первую форму можно вставить ссылку на фото с внешнего сайта, нажать кнопку "загрузить" и фото загрузится на сервер.
Во второй форме загрузка идет с выбором файлов с локального компьютера. (Но если вместо файла в нее вставить ссылку с внешнего сайта, то все тоже прекрасно загружается).
То есть обработчик второй формы (zagruzka_foto()) подходит и для загрузки по ссылке. Из второй формы берется var myfiles=$('#photoimg').prop('files') и отправляется в скрипт обработчик zagruzka_foto(myfiles) и дальше уже происходит загрузка.
Мне надо чтобы используя один js-обработчик первая форма тоже заработала. Где мне взять такой объект в первой форме, чтобы передать его в обработчик $('#photoimg').prop('files') ?




Вторая форма готова и полностью работает. Вот ее часть кода:
<form name="upload_form">
 <div id="imageloadbutton" style="display: block;">
    <input id="photoimg" name="photos[]" multiple="true" type="file">
 </div>
</form>
// функция ajax загрузки фото 
	 $('#photoimg').change(function() { 
                var myfiles = $('#photoimg').prop('files');
		zagruzka_foto(myfiles); // передаем объект Filelist в функцию для ajax отправки файлов на сервер 
	});


Первая форма:
<form id="load_pic">
 <input value="" title="Вставьте сюда прямую ссылку на фотографию товара с сайта поставщика" maxlength="300" id="sp_load_photo" style="height:20px;width:300px;" placeholder="Доступные форматы: gif, jpg, png, bmp" type="text">
 <input id="iditem" value="1898470" type="hidden"><input value="Закачать" onclick="zagruzka_foto();" type="button">
</form>


Упрощу вопрос:
Вторая форма рабочая. Берет значение $('#photoimg').prop('files') и отправляет его в функцию загрузки:zagruzka_foto(myfiles)
Первая форма не рабочая. Как и что нужно передать в функцию zagruzka_foto()?

laimas 11.02.2018 19:37

kupidon,
для загрузи файла из сети, не файлы на сервер надо грузить, а передавать текстовым поле url к этому файлу, загружать его уже будет сам сервер.

Leon-on12 11.02.2018 19:59

Первая самая очевидная вещь, что вы на onclick ничего в функцию zagruzka_foto не передаёте, хорошо бы туда передать значение из
<input value="" title="Вставьте сюда прямую ссылку на фотографию товара с сайта поставщика" maxlength="300" id="sp_load_photo" style="height:20px;width:300px;" placeholder="Доступные форматы: gif, jpg, png, bmp" type="text">

Второе:
Что бы не разбираться в функции zagruzka_foto() и рассмотрении как же эта функция ищет форму что бы её отправить, я бы обернул этой самой формой оба инпута, и засылал бы значение активированного.
<form name="upload_form">
    <div class="inputWrapper">
        <input value="" title="Вставьте сюда прямую ссылку на фотографию товара с сайта поставщика" maxlength="300" id="sp_load_photo" style="height:20px;width:300px;" placeholder="Доступные форматы: gif, jpg, png, bmp" type="text">
3
        <input id="iditem" value="1898470" type="hidden"><input value="Закачать" onclick="zagruzka_foto($('#sp_load_photo').prop('value'));" type="button">
    </div>
    <div id="imageloadbutton" style="display: block;">
        <input id="photoimg" name="photos[]" multiple="true" type="file">
    </div>
</form>

Не работал с атрибутом files, но что-то мне подсказывает что он идентичен пути по этому вместо .prop('files') используем .prop('value'), так же не очень люблю jQuery и написал бы чистое решение:
zagruzka_foto(documentGetElementById('sp_load_photo').value)

Не уверен что всё это будет работать, но я очень надеюсь, что хоть чем то помог.

kupidon 13.02.2018 19:44

Спасибо Вам за ответы, но что-то все равно не получается.
вот что я делаю: отправляю ссылку на картинку (с другого сайта) из инпута в функцию zagruzka_foto(). Но он не хочет такое отправлять на сервер.


llfoto="$('#sp_load_photo').prop('value')"


<form id="load_pic">
	<input value="" title="Вставьте сюда прямую ссылку на фотографию товара с сайта поставщика" maxlength="300" id="sp_load_photo" type="text" placeholder="Доступные форматы: gif, jpg, png, bmp">
	<input value="Закачать" onclick="zagruzka_foto('+llfoto+') type="button">
	</form>


// Функция загрузки фото 
function zagruzka_foto(myfiles){
	      function count(obj) {
	          var count = 0; 
	          for(var prs in obj) { 
	             if(obj.hasOwnProperty(prs)) count++;
	    	  } 
	          return count; 
	       }
	 
	    for(var i = 0; i < count(file_data); i++){
	    	var form_data = new FormData(); 
		var file_dat000 = myfiles[i];
	    form_data.append('file', file_dat000);
	    $.ajax({
	                url: 'include/upload_photo/ajax_upload.php',
	                dataType: 'text',
	                cache: false,
	                contentType: false,
	                processData: false,
	                data: form_data,
	                type: 'post',
	                beforeSend:function(){ },
	                success: function(response){  },
	                error: function(){   },
	                complete: function(){  },
	     });
		}



Почему при если инпут type="file" то загрузка происходит, а если =text то нет?
Может быть ссылку преобразовать в тип файл каким то образом? не понимаю как сделать ((

laimas 14.02.2018 06:52

Цитата:

Сообщение от kupidon
Может быть ссылку преобразовать в тип файл каким то образом?

Поле file не загружает сетевые файлы и подменить ему путь загрузки на свой произвольный нельзя, это политика безопасности.

Файлы выбранные пользователем, это будет $_FILES, а то что он выбрал по сети, это $_POST содержащий ссылку на источник. Серверу нужно получить файл по этому источнику - file_get_contents(url).

kupidon 14.02.2018 14:51

Смотрите: если я нажимаю кнопку обзор, открывается диалоговое окно для выбора локальных файлов. В это окно я вставляю ссылку на фото со стороннего сайта. Нажимаю ОК. И в этом случае фотка со стороннего сайта прекрасно грузится на сервер, как будто это локальный файл.

То есть нельзя подстроиться под действующую функцию загрузки?

laimas 14.02.2018 15:16

Цитата:

Сообщение от kupidon
Смотрите: если я нажимаю кнопку обзор, открывается диалоговое окно для выбора локальных файлов. В это окно я вставляю ссылку на фото со стороннего сайта.

Нет такого диалога.

Nexus 14.02.2018 15:26

Цитата:

Сообщение от laimas
Нет такого диалога.

Это стандартный диалог выбора файла.
Если туда ссылку на удаленный файл вставить, то он будет скачан и сохранен во временных файлах, а ссылка на него будет помещена в input file.

Alexandroppolus 14.02.2018 15:37

Цитата:

Сообщение от Nexus
Это стандартный диалог выбора файла.
Если туда ссылку на удаленный файл вставить, то он будет скачан и сохранен во временных файлах, а ссылка на него будет помещена в input file.

так во всех браузерах? впервые слышу про такое

Nexus 14.02.2018 15:43

Цитата:

Сообщение от Alexandroppolus
так во всех браузерах? впервые слышу про такое

Понятия не имею, сам только после прочтения шестого комментария и его проверки об этом узнал )

laimas 14.02.2018 15:46

Цитата:

Сообщение от Nexus
Если туда ссылку на удаленный файл вставить, то он будет скачан и сохранен во временных файлах, а ссылка на него будет помещена в input file.

Где это? Поле file открывает диалог работающий в пределах локальной дисковой системы, вставить в поле file путь к произвольному файлу нельзя, в противном случае файлы системы имеющие ценную информацию массово бы утекали охотникам за ними.

Для сетевых файлов практически нужно открывать браузер. Ну допустим сделали такую фичу, но зачем? Загружать на сервер сетевой файл через клиента, это просто глупость.

laimas 14.02.2018 15:48

Цитата:

Сообщение от Nexus
сам только после прочтения шестого комментария и его проверки об этом узнал )

Так это сарказм был? )

Alexandroppolus 14.02.2018 15:51

Цитата:

Сообщение от kupidon
В это окно я вставляю ссылку на фото со стороннего сайта

не знаю как на винде, а на макбуке у этого окна некуда воткнуть ссылку, нет текстового поля

Nexus 14.02.2018 15:52

Цитата:

Сообщение от laimas
Поле file открывает диалог работающий в пределах локальной дисковой системы

Оказывается не только в пределах локальной дисковой системы.
Цитата:

Сообщение от laimas
в противном случае файлы системы имеющие ценную информацию массово бы утекали охотникам за ними.

Не понимаю как вы пришли к такому умозаключению.

Цитата:

Сообщение от laimas
Загружать на сервер сетевой файл через клиента, это просто глупость.

Не поспоришь, однако такое возможно.

Win7, Максимальная
Google Chrome v.64.0.3282.140

Nexus 14.02.2018 15:53

Цитата:

Сообщение от laimas
Так это сарказм был? )

Нет, не сарказм.

laimas 14.02.2018 16:05

Цитата:

Сообщение от Nexus
Не понимаю как вы пришли к такому умозаключению.

Я имел ввиду программно менять значение поля, а не диалогом, что делает пользователь сознательно.

Цитата:

Сообщение от Nexus
Не поспоришь, однако такое возможно.

Win7, Максимальная
Google Chrome v.64.0.3282.140

И тупо и глупо. ) Нормальный браузер ничего не будет качать с сервера.
Другое дело, если есть пусть хост картинок, которые клиент может получать, творить с ними, а результат сохранять на свой сервер. Тогда оправдано через клиента. Но поля file для этого не требуется.

laimas 14.02.2018 16:10

Проверил и в Хроме. О чем речь? Если в окне диалога вместо имени вставить ссылку, это не проблема, это не только в хроме можно, а в каком угодно, даже покажет имя файла, если это имя. Но на сервере пусто, если только не сырые данные еще проверить.

Alexandroppolus 14.02.2018 16:15

Цитата:

Сообщение от laimas
Серверу нужно получить файл по этому источнику - file_get_contents(url)

если файл доступен только для внутренней сети или при авторизации, то такой вариант не сработает. Хотя, конечно, это редкий кейс.

laimas 14.02.2018 16:19

Цитата:

Сообщение от Alexandroppolus
если файл доступен только для внутренней сети или при авторизации

Ну а откуда ссылка внутренней сети может оказаться в глобальной? Ежику понятно, что не получится. :) Или имеется ввиду закрытая сеть?

Nexus 14.02.2018 16:21

Цитата:

Сообщение от laimas
Но на сервере пусто, если только не сырые данные еще проверить.

Если данные на сервер не были отправлены, значит проблема в форме, которая их отправляет либо в сервере.

laimas 14.02.2018 16:29

Да, отправляет. Это у меня закрыто просто было. )

Ну это же тупость полнейшая, что даже и не подозревал об этом. :)

Лиса тоже отправляет.

Alexandroppolus 14.02.2018 16:35

Цитата:

Сообщение от laimas
Или имеется ввиду закрытая сеть?

да.
такая, что сервер автора топика её не видит

kupidon 15.02.2018 05:26

Ну ведь работает же! У меня из стандартной формы грузит и потом прекрасно обрабатывается. Согласен, что это тупо так загружать. Поэтому и ищу решение. Но поскольку я в этом деле любитель- оно мне кажется сложновато.

Цитата:

Сообщение от Nexus (Сообщение 478104)
Это стандартный диалог выбора файла.
Если туда ссылку на удаленный файл вставить, то он будет скачан и сохранен во временных файлах, а ссылка на него будет помещена в input file.

Выбирая локальные файлы в стандартном диалоговом окне , после нажатия кнопки ОК, они сразу перемещаются во временные файл? или только когда js-скрипт их туда отправит? в моем случае скрипт срабатывает при завершении выбора файлов.

В php обработчик приходит временный файл. И там уже обрабатывается
Можно ли сделать, чтобы из сторонней ссылки, из поля формы input, в обработчик приходил точно такой же временный файл?
Чтобы использовать один обработчик.

laimas 15.02.2018 05:55

Цитата:

Сообщение от kupidon
В php обработчик приходит временный файл.

НА сервер приходит просто файл, который выбрал пользователь, он помещается во временную папку под временным именем. Если он не будет перенесен из временной папки, его удалит сборщик мусора.

Цитата:

Сообщение от kupidon
Можно ли сделать, чтобы из сторонней ссылки, из поля формы input, в обработчик приходил точно такой же временный файл?
Чтобы использовать один обработчик.

А как можно использовать два и более обработчика, если файл и сетевой будет передан формой?

Nexus 15.02.2018 08:05

Цитата:

Сообщение от kupidon
Выбирая локальные файлы в стандартном диалоговом окне , после нажатия кнопки ОК, они сразу перемещаются во временные файл? или только когда js-скрипт их туда отправит?

JS на стороне клиента не может работать с файловой системой.
Временные файлы создаются только для файлов, которые нужно скачать из сети.

kupidon 15.02.2018 09:16

Цитата:

Сообщение от laimas (Сообщение 478157)
НА сервер приходит просто файл, который выбрал пользователь, он помещается во временную папку под временным именем. Если он не будет перенесен из временной папки, его удалит сборщик мусора.

как же мне тогда отправить на сервер из ссылки временный файл? я вообще запутался

Цитата:

Сообщение от laimas (Сообщение 478157)
А как можно использовать два и более обработчика, если файл и сетевой будет передан формой?

ну по факту то формы две получается. Одна для локального файла. другая для сетевого.
Получается вторая форма (для локального файла) отправляет на сервер временный файл и указывает ему php- обработчик.

А в первой форме только ссылка. Как мне ее заставить работать: подгрузить на сервер сетевой файл и указать этот же php обработчик?

laimas 15.02.2018 09:27

Цитата:

Сообщение от kupidon
ну по факту то формы две получается.

Ну это если с дури каждое поле в свою форму. :)

Но в этом случае одновременно два файла нельзя отправить на сервер. Два поля в одной форме, и если одно имеет имя "name1", а второе "name2", то на сервере в массиве $_FILES они будут под этими ключами. Но смысла так их разделять нет никакого, задайте обеим полям одно имя как элементы массива - name[], и под этим ключом в массиве $_FILES будет массив из двух файлов.

Это если передавать сетевой файл через форму. Если это не для всех пользователей, то на здоровье. Иначе извещайте их как это делать, уверен, что большая часть об этом даже и не подозревает, я вот не знал и не считаю это нужным.

А если серверу передавать ссылку, то это обычное текстовое поле и оно будет под его именем как ключом в массиве $_POST. Сервер его должен загрузить, при этом обработка загрузки, как-то проверка типа, размера, действия на файлами какие либо, и будет одним сценарием. Источники просто разные.

kupidon 15.02.2018 11:18

Я имел ввиду не два диалоговых окна, а две html формы. Одна с диалоговым окном, другая просто текстовое для ссылки.


Как я уже писал выше, что через первую я уже могу загрузить, но это неудобно и мне надо сделать вторую для этого. Вечером задам вопрос более детально с использованием кода. Все на домашнем компе, на денвере. Спасибо Вам что помогаете.

laimas 15.02.2018 11:22

Цитата:

Сообщение от kupidon
Я имел ввиду не два диалоговых окна, а две html формы.

А зачем две формы, что одной нельзя загрузить и файлы и текст?

kupidon 15.02.2018 12:31

Цитата:

Сообщение от laimas (Сообщение 478178)
А зачем две формы, что одной нельзя загрузить и файлы и текст?

Может и можно, но не по Сеньке шапка видимо)). Вечером напишу что там наваял.

laimas 15.02.2018 12:51

Цитата:

Сообщение от kupidon
Может и можно

Не можно, а нужно, особенно если добавление для нового товара.

kupidon 15.02.2018 18:24

Вот мои две формы. Первая не рабочая, вторая рабочая.
<form id="load_pic">
<input value="" title="Вставьте сюда прямую ссылку на фотографию товара с сайта поставщика" maxlength="300" id="sp_load_photo"  placeholder="Доступные форматы: gif, jpg, png, bmp" type="text">
<input value="Закачать" onclick="" type="button">
</form>

<form name="upload_form">
<div id="imageloadbutton">
<input id="photoimg" name="photos[]" multiple="true" type="file">
</div>
<div id="imageloadstatus" style="display:none">
<img src="include/upload_photo/loader.gif" alt="Загрузка ...">
<span>Идет загрузка...</span>
</div>
</form>


// функция ajax загрузки фото 
	 $('#photoimg').change(function() { 
	    var myfiles = $('#photoimg').prop('files');
	    for(var i = 0; i < count(file_data); i++){
	    	var form_data = new FormData(); 
		var file_dat000 = myfiles[i];
	    form_data.append('file', file_dat000);
	    $.ajax({
	                url: 'include/upload_photo/ajax_upload.php',
	                dataType: 'text',
	                cache: false,
	                contentType: false,
	                processData: false,
	                data: form_data,
	                type: 'post',
	                success: function(response){
		                $("#imageloadstatus").hide();
				$("#imageloadbutton").show();
	 			show_picture(response);
	                },
	                error: function(){
		 		$("#imageloadstatus").hide();
				$("#imageloadbutton").show();               	
	                },
	                complete: function(){
		 		$('#photoimg').val('');
	                },
	     });
		}
	});


и обработчик ajax_upload.php:
if (isset($_POST) and $_SERVER["REQUEST_METHOD"] == "POST")
{
    if ( 0 < $_FILES['file']['error'] ) {
        echo 'Error: ' . $_FILES['file']['error'] . '<br>';
    } else {....
....
$filename = stripslashes($_FILES['file']['name']); // полный путь файла
.....


Подскажите, пожалуйста, как мне в этот обработчик отправить данные с первой формы, чтобы произошла загрузка временного файла с внешнего URL ?

laimas 15.02.2018 18:43

Цитата:

Сообщение от kupidon
и обработчик ajax_upload.php:

Первая форма ничего не закачивает, и в никаких $_FILES ловить ее данные не стоит.

Проверка if (isset($_POST) никчемная да и отношение к $_FILES не имеющая, и $_SERVER["REQUEST_METHOD"] == "POST" выбросить тоже.

Цитата:

Сообщение от kupidon
stripslashes($_FILES['file']['name']); // полный путь файла

Ни дай бог путь! Клиент никогда не передаст серверу локальный пусть файла, а если не имя, а путь передан, то это подстава и опасная. Поэтому обязательно basename($_FILES['file']['name']), но только зачем же товарам добавлять имена типа "Это я в Сочи", "Это у моря"?

В предыдущих темах ведь говорилось уже о добавлении товаров и изображений им. Эта форма/формы для добавления фото добавляемому товару или уже добавленному?

kupidon 15.02.2018 19:33

товар есть. Нужно загрузить фото по ссылке, обработать его( переименовать, изменить размеры), переместить и прописать в БД принадлежность к данному ид товара
Но меня интересует только то что касается ссылки. Остальное я уже сделал

kupidon 15.02.2018 19:34

Цитата:

Сообщение от laimas (Сообщение 478272)
Первая форма ничего не закачивает, и в никаких $_FILES ловить ее данные не стоит.

Это я знаю, потому что не знаю как сделать. Впрочем об этом и топик.

kupidon 15.02.2018 20:20

Я чувствую что я уже где то близко:
<div style="padding:2px;font-size:8pt;">Загрузить с компьютера: 
<input id="test" type="text" name="url_file" style="width:200px" value="http://">
</div>
<input value="Загрузить" type="button" style="width:100px;margin-left:136px" onclick="javascript:sss();">


function sss(){
	var res=$('#test').val();
	alert(res);
	     		$.ajax({
	    type: "POST",
	    url: "include/upload_photo/ajax_upload.php",
	    data: ("file_url="+res),
	    dataType: "html",
	    cashe: false,
	    success: function(msg){
	    	alert(msg);
	     },
	    error: (function() { 
	    	alert("Ошибка выполнения"); 
	    }),
	 	});	 
}


if (isset($_POST) and $_SERVER["REQUEST_METHOD"] == "POST")
{
$contents = file_get_contents($_POST['file_url']);
echo $contents;
}


Вот тут ошибку возвращает. Как мне правильно загрузить файл и привести его к $_FILES['file']?, чтобы продолжить в тех же функциях обработчика

laimas 15.02.2018 20:21

Цитата:

Сообщение от kupidon
Но меня интересует только то что касается ссылки. Остальное я уже сделал

Если сделано так как в коде, то это никуда не годится.

Цитата:

Сообщение от kupidon
товар есть. Нужно загрузить фото по ссылке, обработать его( переименовать, изменить размеры), переместить и прописать в БД принадлежность к данному ид товара

Значит редактирование/обновление товара, следовательно либо в форме есть скрытое поле со значением id товара, либо id товара, это ключ в имени полей формы.

Одной формой можно добавлять как локальные файлы, так указывать загрузку сетевых файлов.

<form>
<div id="url_file">
<input name="file[]" />
</div>
<div id="local_file">
<input type="file" name="file[]" />
</div>
<input type="hidden" name="id" value="<?=$id?>" />
</form>

Поле file[] бокса url_file можно клонировать тем самым определять для загрузки множество файлов. Поле file[] бокса local_file также может загружать множество файлов, нужно только проверять на клиенте при выборе файлов соответствие выбранного ограничениям накладываемых сервером.

На сервере если передан id товара и если это действительно товар имеющийся в базе, а не просто число, то загрузка файлов, если массив $_FILES не пуст.

Обходом в цикле загружаем файлы загруженные без ошибок - !file["error"][$i]. Если файл отвечает требованиям: тип, размер если определено, то file["tmp_name"][$i] передается в функцию на обработку: изменение размеров, обрезка, наложение логотипа и т.п. Если все Ок, эта функция генерирует имя файла, а не использует загруженное "Огурцы на грядке", даже если товар и огурец, и под этим именем сохраняет в указанном каталоге (если каталоги связаны к примеру с категориями, помимо id товара сервер должен знать и о категории). Эта же функция может обновлять и запись в базе о новом добавленном фото, либо возвращать его из функции, одновременно указывая им и удачное выполнение. Имена всех возвращенных функцией файлов одним запросом по окончании загрузки записать в базу. Если есть ошибки, то функция возвращает false.

Если массив $_POST["file"] не пуст, то в цикле загружается сетевой файл по указанному url, также проверяется на условия по типу/размеру, и отдается в функцию на обработку.

То есть, если есть загруженные $_FILES и указаны сетевые, то и те, и другие обрабатываются одной функцией. Либо одни из - локальные или сетевые. Если и то, и другое пусто - ошибка.

laimas 15.02.2018 20:24

Цитата:

Сообщение от kupidon
isset($_POST)

Это всегда вернет истину ибо $_POST суперглобальный массив и всегда в наличии.

kupidon 15.02.2018 20:27

Цитата:

Сообщение от laimas
Проверка if (isset($_POST) никчемная да и отношение к $_FILES не имеющая, и $_SERVER["REQUEST_METHOD"] == "POST" выбросить тоже.

Вообще проверку убрать?

Цитата:

Сообщение от laimas
Поэтому обязательно basename($_FILES['file']['name']

У меня переименованием файла занимается отдельная функция, это мне не надо наверное.

kupidon 15.02.2018 20:40

Цитата:

Сообщение от laimas
Если массив $_POST["file"] не пуст, то в цикле загружается сетевой файл по указанному url, также проверяется на условия по типу/размеру, и отдается в функцию на обработку.

как его загрузить? что то не получается у меня((
Вот нашел в инете пример:
$file = 'https://www.google.ru/images/srpr/logo11w.png';
$file_name = basename('https://www.google.ru/images/srpr/logo11w.png');
file_put_contents('my_folder'.$file_name, file_get_contents($file));

И как из этого примера потом получить ссылку на временный файл?


Часовой пояс GMT +3, время: 20:16.