#ajax #laravel #file #controller #request
#ajax #laravel #файл #контроллер #запрос
Вопрос:
У меня есть форма с вводом типа file hidden. Тег изображения работает как триггер для выбора самого файла, с помощью js для его запуска (это работает), но я хочу автоматически отправлять запрос PUT при выборе изображения вместо того, чтобы нажимать кнопку отправки в форме каждый раз, когда изображение изменяется в поле ввода. Для этого я использую ajax, но на конечной точке контроллера, которая обрабатывает запрос, у меня, похоже, нет никакого файла. Однако, если я добавляю другие поля, такие как текстовые, они, похоже, передаются в контроллер через запрос просто отлично.
Мой маршрут:
Route::put('/coins/image/{key}', [CoinController::class, 'image'])->name("coins.image");
Мой контроллер (пока нет фактического кода обновления изображения; только то, что я делаю для проверки файла):
public function image(int $key)
{
dump(request()->file('file'));
dump(request()->file);
dump(request());
}
Мой HTML и JS в следующем фрагменте:
function promptImageForUpload(elemId)
{
$('#' elemId).click();
}
function uploadImage(event, imgId, key)
{
event.preventDefault();
var inputElem = event.target;
var imageFile = inputElem.files[0];
var imgElem = $('#' imgId);
var form = $(inputElem).parent();
var formData = new FormData(form[0]);
formData.append('file', imageFile);
$.ajax({
url: "/coins/image/" key,
type: "PUT",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: formData,
enctype: 'multipart/form-data',
processData: false,
contentType: false,
success: function(response) {
var reader = new FileReader();
reader.onload = function(e) {
imgElem.attr("src", e.target.result);
};
reader.readAsDataURL(imageFile); // convert to base64 string
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card-body">
<form data-key="0" id="coin-header-0_form" method="POST" action="#" enctype="multipart/form-data">
<input type="file" name="file" id="coin-header-0_file" style="z-index:-1; width: 100%; height: 100%; display: none;" onchange="uploadImage(event, 'coin-header-0_preview', 0)">
<input type="hidden" name="_method" value="PUT">
<meta name="csrf-token" content="7c3s2NmosdK9qzrS10xGAB0rYXw5g41azRjcmPQC">
<img src="http://snapbuilder.com/code_snippet_generator/image_placeholder_generator/60x40/007730/DDDDDD/this pict" width="50px" height="50px" alt="icon" id="coin-header-0_preview" onclick="promptImageForUpload('coin-header-0_file');">
</form>
</div>
На данный момент я принудительно обновляю предварительный просмотр изображения при успешном выполнении ajax вместо того, чтобы извлекать его из обновленного объекта после успешного обновления, чтобы избежать второго запроса.
У меня установлен метод PUT для подмены в запросе ajax, а токен xsrf также задает заголовки. Для Enctype также задано значение multipart / form-data для файлов. Я понятия не имею, почему я не вижу загруженный файл нигде в запросе.
Используя Laravel Framework 8.25.0, jquery 3.5.1.
Пожалуйста, дайте мне знать, если кому-нибудь понадобится дополнительная информация. Я не смог найти никакого решения ни в одной записи stackoverflow или где-либо еще, что касается этой темы. Любая помощь очень ценится, так как я действительно не знаю, как еще взглянуть на это с точки зрения подхода к отладке.
Ответ №1:
HTML-формы не поддерживают PUT
PATCH
или DELETE
действия. Итак, при определении PUT
PATCH
DELETE
маршрутов or, которые вызываются из HTML-формы, вам нужно будет добавить скрытое _method
поле в форму. Значение, отправленное с _method
полем, будет использоваться в качестве метода HTTP-запроса:
<form action="/foo/bar" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
Вы можете использовать помощник method_field для генерации ввода _method:
{{ method_field('PUT') }}
Таким же образом эта проверка может также повлиять на формы ajax. Затем в вашей форме переключитесь на метод POST и установите параметр PUT, чтобы он работал.
Комментарии:
1. Заранее спасибо. После большого пересмотра кода я заметил, что пропустил метод в форме GET. Я знаю, что формы не поддерживают другие методы, кроме GET и POST, но я подумал, что параметр «type: PUT» в запросе ajax будет подделывать метод, подобный Laravel @method (‘PUT’). Я предполагаю, что это не делает то, для чего я думал, что это предназначено, я добавил новое скрытое поле в форму, как вы предложили, но отправленный файл по-прежнему остается пустым. Обновляю вопрос, чтобы отразить ваши предложения, которые уже есть, и с выводом для дампа запроса.