I tried several ways to make a chunked upload but did not work with me anyway and I still try but without benefit, Any help, I want to use this package:
pionl/laravel-chunk-upload
Upload files via AJAX with jQuery and chunked upload,
That's what I tried:
<script type="text/javascript" src="{{ asset('js/jquery.iframe-transport.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/jquery.fileupload.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/jquery.ui.widget.js') }}"></script>
<div class="text-center">
<input id="fileupload" type="file" name="file" data-url="{{ url('upload') }}" style="display: inline;">
<ul id="file-upload-list" class="list-unstyled">
</ul>
</div>
<script type="text/javascript">
var $ = window.$; // use the global jQuery instance
var $uploadList = $("#file-upload-list");
var $fileUpload = $('#fileupload');
if ($uploadList.length > 0 && $fileUpload.length > 0) {
var idSequence = 0;
// A quick way setup - url is taken from the html tag
$fileUpload.fileupload({
maxChunkSize: 1000000,
method: "POST",
// Not supported
sequentialUploads: false,
formData: function (form) {
// Append token to the request - required for web routes
return [{name: '_token', value: $('input[name=_token]').val()}];
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$("#" + data.theId).text('Uploading ' + progress + '%');
},
add: function (e, data) {
data._progress.theId = 'id_' + idSequence;
idSequence++;
$uploadList.append($('<li id="' + data.theId + '"></li>').text('Uploading'));
data.submit();
},
done: function (e, data) {
console.log(data, e);
$uploadList.append($('<li></li>').text('Uploaded: ' + data.result.path + ' ' + data.result.name));
}
});
}
</script>
My Controller:
public function upload(Request $request) {
// create the file receiver
$receiver = new FileReceiver("file", $request, HandlerFactory::classFromRequest($request));
// check if the upload is success, throw exception or return response you need
if ($receiver->isUploaded() === false) {
throw new UploadMissingFileException();
}
// receive the file
$save = $receiver->receive();
// check if the upload has finished (in chunk mode it will send smaller files)
if ($save->isFinished()) {
// save the file and return any response you need, current example uses `move` function. If you are
// not using move, you need to manually delete the file by unlink($save->getFile()->getPathname())
return $this->saveFile($save->getFile());
}
// we are in chunk mode, lets send the current progress
/** #var AbstractHandler $handler */
$handler = $save->handler();
return response()->json([
"done" => $handler->getPercentageDone(),
'status' => true
]);
}
Any successful way to do that?
Related
i'm trying to use pionl/laravel-chunk-upload and Resumable.js to upload large file into server
i implemented view, controller and route and now when i try to upload file i get this error:
Symfony\Component\HttpFoundation\File\Exception\FileException: The
file "XXXXXXXX" was not uploaded due to an unknown error. in file
C:\xampp\htdocs\XXX\vendor\symfony\http-foundation\File\UploadedFile.php
on line 213
and i can't fix this error:
view:
<div class="form-group">
<div class="resumable-error">
Your browser, unfortunately, is not supported by Resumable.js. The library requires support for the HTML5 File API along with file slicing.
</div>
<div class="resumable-drop">
Drop video files here to upload or <a class="resumable-browse"><u>select from your computer</u></a>
</div>
<div class="resumable-progress">
<table>
<tr>
<td style="width: 100%"><div class="progress-container"><div class="progress-bar"></div></div></td>
<td class="progress-text" nowrap="nowrap"></td>
<td class="progress-pause" nowrap="nowrap">
<img src="/assets/global_assets/images/icons/resume.png" title="Resume upload" />
<img src="/assets/global_assets/images/icons/pause.png" title="Pause upload" />
<img src="/assets/global_assets/images/icons/cancel.png" title="Cancel upload" />
</td>
</tr>
</table>
</div>
<ul class="nav nav-sidebar mb-2 resumable-list p-0 pl-3 m-0" data-nav-type="accordion"></ul>
</div>
<script>
var r = new Resumable({
target: '/panel/uploadRadioChannelFile',
chunkSize: 1 * 1024 * 1024,
testChunks: false,
throttleProgressCallbacks: 1,
headers:{
'X-CSRF-Token' :"{{ csrf_token() }}"
},
query:{
_token : "{{ csrf_token() }}"
}
});
// Resumable.js isn't supported, fall back on a different method
if (!r.support) {
$('.resumable-error').show();
} else {
// Show a place for dropping/selecting files
$('.resumable-drop').show();
r.assignDrop($('.resumable-drop')[0]);
r.assignBrowse($('.resumable-browse')[0]);
// Handle file add event
r.on('fileAdded', function (file) {
// Show progress pabr
$('.resumable-progress, .resumable-list').show();
// Show pause, hide resume
$('.resumable-progress .progress-resume-link').hide();
$('.resumable-progress .progress-pause-link').show();
// Add the file to the list
$('.resumable-list').append('<li class="nav-item resumable-file-' + file.uniqueIdentifier + '">Uploading <span class="resumable-file-name"></span> <span class="resumable-file-progress"></span>');
$('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-name').html(file.fileName);
// Actually start the upload
r.upload();
});
r.on('pause', function () {
// Show resume, hide pause
$('.resumable-progress .progress-resume-link').show();
$('.resumable-progress .progress-pause-link').hide();
});
r.on('complete', function () {
// Hide pause/resume when the upload has completed
$('.resumable-progress .progress-resume-link, .resumable-progress .progress-pause-link').hide();
});
r.on('fileSuccess', function (file, message) {
// Reflect that the file upload has completed
$('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html('(completed)');
});
r.on('fileError', function (file, message) {
// Reflect that the file upload has resulted in error
$('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html('(file could not be uploaded: ' + message + ')');
});
r.on('fileProgress', function (file) {
// Handle progress for both the file and the overall upload
$('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html(Math.floor(file.progress() * 100) + '%');
$('.progress-bar').css({width: Math.floor(r.progress() * 100) + '%'});
});
r.on('cancel', function () {
$('.resumable-file-progress').html('canceled');
});
r.on('uploadStart', function () {
// Show pause, hide resume
$('.resumable-progress .progress-resume-link').hide();
$('.resumable-progress .progress-pause-link').show();
});
}
</script>
route:
Route::post('uploadRadioChannelFile', 'UploadController#upload');
and controller:
class UploadController extends Controller
{
public function upload(Request $request)
{
try {
$receiver = new FileReceiver("file", $request, HandlerFactory::classFromRequest($request));
if ($receiver->isUploaded() === false) {
return response()->json([
"done" => '',
'status' => false
]);
}
$save = $receiver->receive();
if ($save->isFinished()) {
return $this->saveFile($save->getFile());
}
$handler = $save->handler();
return response()->json([
"done" => $handler->getPercentageDone(),
'status' => true
]);
} catch (UploadFailedException $e) {
}
}
protected function saveFile(UploadedFile $file)
{
$fileName = $this->createFilename($file);
//$mime = str_replace('/', '-', $file->getMimeType());
$dateFolder = Carbon::now()->year;
$public_html = config('app.public_path');
$filePath = "upload/{$dateFolder}/";
$file->move($public_html.$filePath, $fileName);
return response()->json([
'path' => $filePath,
'name' => $fileName,
'ffff' => $file->getClientOriginalName(),
]);
}
protected function createFilename(UploadedFile $file)
{
//$extension = $file->getClientOriginalExtension();
//$filename = str_replace("." . $extension, "", $file->getClientOriginalName()); // Filename without extension
//$filename .= "_" . md5(time()) . "." . $extension;
return time() . '.' . $file->getClientOriginalExtension();
}
}
I have tried majority of other questions here and other solutions and nothing has worked so far.
What I am trying to accomplish is upload images before Laravel's validation takes place, obviously I can't use the create function because it wont be hit until validation succeeds so I have made a custom function to do the file saving server side and trying to use Ajax to call that function every time a file is selected.
Current issue: doesn't seem like my Ajax is running on debugging its being skipped over,
second issue: I have a csrf token in my master template do i still need to add the ajax setup? if so is the way i am doing it correct.
Route:
Route::post('/upload', 'UploadController#uploadSubmit');
View:
<div>
<input type="file" id="fileupload" name="photos[]" data-url="/upload" multiple />
<br />
<div id="files_list"></div>
<p id="loading"></p>
<input type="hidden" name="file_ids" id="file_ids" value="" />
</div>
Ajax call:
$(document).ready(function(){
$("input").change(function(){
alert('triggered');
debugger;
$('#fileupload').fileupload({
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $(meta[name="csrf-token"]).attr('content')
}
dataType: 'json',
add: function (e, data) {
$('#loading').text('Uploading...');
data.submit();
},
done: function (e, data) {
$.each(data.result.files, function (index, file) {
$('<p/>').html(file.name + ' (' + file.size + ' KB)').appendTo($('#files_list'));
if ($('#file_ids').val() != '') {
$('#file_ids').val($('#file_ids').val() + ',');
}
$('#file_ids').val($('#file_ids').val() + file.fileID);
});
$('#loading').text('');
}
});
});
});
});
Controller:
public function uploadSubmit(Request $request){
$files = [];
dd(request());
foreach($learnerFiles as $key => $learnerFile){
if(count($learnerFile) > 0){
$path = $learnerFile->storeAs('public/uploads/learners', request('idNumber').'_'.$key.'.'.$learnerFile->extension());
$search = 'public/' ;
$trimmed = str_replace($search, '', $path) ;
//dd($learnerFiles);
$file = FileUpload::create([
'user_id' => $learner->id,
'file_name' => $key,
'path' => $trimmed
]);
}
else{
}
$file_object = new \stdClass();
$file_object->name = $key;
$file_object->size = round(Storage::size($path) / 1024, 2);
$file_object->fileID = $learner->id;
$files[] = $file_object;
}
return response()->json(array('files' => $photos), 200);
}
I'm using the following method to upload images using Ajax call and Laravel back-end.
var uploader = $('#image-uploader[type="file"]');
var data = new FormData();
$.each(uploader.files, function() {
data.append('image[]', this);
});
data.append('_token', $('[name="csrf-token"]').attr('content'));
var url = '/upload'; //Or any target path with post method
$.ajax({
url: url,
method: 'POST',
data: data,
processData: false,
contentType: false,
success: function(data) {
alert('succeed');
}
});
Consider you can access to image files in server-side using $_POST['image] array.
Hope this helps you.
I am using wordpress 4.8, contactform7 4.8 and jquery file upload
and trying to add multiple file upload support in contact form 7.
now, my script is
( function( $ ) {
'use strict';
var url = window.location.hostname === 'blueimp.github.io' ?
'//jquery-file-upload.appspot.com/' : ajax_object.ajax_url;
$('.wpcf7-multifile').fileupload({
url: url,
dataType: 'json',
autoUpload: true,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 99900000,
// Enable image resizing, except for Android and Opera,
// which actually support image resizing, but fail to
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true
}).on('fileuploadadd', function (e, data) {
//console.log(data.files);
data.context = $('<div/>').appendTo('#files');
data.formData = {action : 'do_file_upload'};
$.each(data.files, function (index, file) {
var node = $('<p/>')
.append($('<span/>').text(file.name));
if (!index) {
node
.append('<br>')
}
node.appendTo(data.context);
});
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index,
file = data.files[index],
node = $(data.context.children()[index]);
if (file.preview) {
node
.prepend('<br>')
.prepend(file.preview);
}
if (file.error) {
node
.append('<br>')
.append($('<span class="text-danger"/>').text(file.error));
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}).on('fileuploaddone', function (e, data) {
console.log(data.result.files);
$.each(data.result.files, function (index, file) {
if (file.url) {
var link = $('<a>')
.attr('target', '_blank')
.prop('href', file.url);
$(data.context.children()[index])
.wrap(link);
} else if (file.error) {
var error = $('<span class="text-danger"/>').text(file.error);
$(data.context.children()[index])
.append('<br>')
.append(error);
}
});
}).on('fileuploadfail', function (e, data) {
//console.log("upload failed");
console.log(e);
$.each(data.files, function (index) {
var error = $('<span class="text-danger"/>').text('File upload failed.');
$(data.context.children()[index])
.append('<br>')
.append(error);
});
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
} )( jQuery );
and this is my UploadHandler.php.
my html is
<p><label> Multi File<br>
<span class="wpcf7-form-control-wrap multifile-966"><input type="file" name="multifile-966[]" size="40" class="wpcf7-form-control wpcf7-multifile multi-file" id="multi-file" multiple="multiple" aria-invalid="false"></span></label></p>
server site ajax callback is
add_action('wp_ajax_do_file_upload', 'do_file_upload');
add_action('wp_ajax_nopriv_do_file_upload', 'do_file_upload');
if ( ! function_exists('do_file_upload') ){
function do_file_upload(){
$options = [
'param_name' => key($_FILES)
];
require('server/php/UploadHandler.php');
$upload_handler = new UploadHandler($options);
}
}
file upload getting failed.
console log for e in fileuploadfail event
n.Event {type: "fileuploadfail", timeStamp: 1500289969495, jQuery112406601460352960828: true, target: input#multi-file.wpcf7-form-control.wpcf7-multifile.multi-file, isTrigger: 3…}
network response {"multifile-966":[{"name":"Beautiful-Nature-Images-Wallpaper-6755.jpg","size":565592,"type":"image\/jpeg","url":"http:\/\/localhost\/contactform7\/wp-content\/uploads\/wpcf7_uploads\/Beautiful-Nature-Images-Wallpaper-6755.jpg","thumbnailUrl":"http:\/\/localhost\/contactform7\/wp-content\/uploads\/wpcf7_uploads\/thumbnail\/Beautiful-Nature-Images-Wallpaper-6755.jpg","deleteUrl":"http:\/\/localhost\/contactform7\/wp-admin\/admin-ajax.php?multifile-96=Beautiful-Nature-Images-Wallpaper-6755.jpg","deleteType":"DELETE"}]}0
expected network dummy response
{files: [,…]}
files
:
[,…]
0
:
{name: "46541-purple-sunrise-over-the-mountains-1920x1200-nature-wallpaper (1).jpg", size: 566874,…}
I converted these two response to array in UploadHandler.php file post method and both are 100% same !!only difference is a 0 at the end
of the json response, may be that is giving some idea, but now I have
no idea why not it is showing file upload failed, the file are getting
uploaded but temporarily when I am refreshing the page, they
disappeared .
also updated UploadHandler.php .
Update
changed
return $this->generate_response($response, $print_response);
to
$print_response = false;
wp_send_json($this->generate_response($response, $print_response));
makes the extra 0 disappeared, but still the upload is temporary, but
expected behavior is upload to be permanent.
update2
in UploadHandler.php for
move_uploaded_file($uploaded_file, $file_path);
I am getting true. echo var_dump(move_uploaded_file($uploaded_file, $file_path)); is true.
changing UploadHandler.php
these two lines
'upload_dir' => dirname(dirname($this->get_server_var('SCRIPT_FILENAME'))) . '/wp-content/uploads/wpcf7_uploads/',
'upload_url' => $wp_content_url . 'wpcf7_uploads/',
to any other folder beside wpcf7_uploads
makes it work.
I changed it to
'upload_dir' => dirname(dirname($this->get_server_var('SCRIPT_FILENAME'))) . '/wp-content/uploads/2017/wpcf7_uploads/',
'upload_url' => $wp_content_url . '2017/wpcf7_uploads/',
I'm using AngularJS v1.6.1, Apache 2.4.10 on Debian with PHP 5.6.24 and I'm trying to upload a file to my server using $http POST service.
On my php.ini, max file size is set to 8Mo, max post size too, upload file is on, and memory size limit is set to 128Mo.
Form:
<input type="file" accept="application/pdf" id="uploadOT" max-files="1" ng-model="uploadOT" name="uploadOT" valid-file required ng-class="{'md-input-invalid':uploadForm.uploadOT.$error.validFile}" />
Angular directive: (when input content change, get a FileReader object and send file)
myModule.directive('validFile', function() {
return {
require: 'ngModel',
link: function(scope, elt, attrs, ctrl) {
ctrl.$setValidity('validFile', elt.val() !== '');
elt.bind('change', function() {
var file = document.getElementById('uploadOT').files;
var reader = new FileReader();
reader.onload = function(e) {
scope.sendFile(reader, scope.id);
};
scope.showUploadProgress = true;
scope.filename = file[0].name;
reader.readAsBinaryString(file[0]);
ctrl.$setValidity('validFile', elt.val() !== '');
scope.$apply(function() {
ctrl.$setViewValue(elt.val());
ctrl.$render();
});
});
}
};
});
Inside controller:
$scope.sendFile = function(reader, id) {
var fd = new FormData();
fd.append('id', id);
fd.append('file', reader.result);
fd.append('MAX_FILE_SIZE', 8 * 1024 * 1024);
$http.post('api/upload.php', fd, {
headers: {'Content-Type' : undefined },
transformRequest: angular.identity
}).then(function() {
alert('upload success');
}, function() {
$scope.showUploadError = true;
$scope.showUploadProgress = false;
$scope.postError = 'Une erreur inconnue est survenue !';
});
};
On server side (file api/upload.php), I print variables $_POST and $_FILES with print_r().
Why is $_FILES always empty, and my file data is in $_POST['file']?
I can create file from $_POST['file'] data with php function file_put_contents() but I cannot make verifications that I can make with $_FILES. Is it really important (security issues)?
If I change my POST Content-Type to multipart/form-data, the same thing happend.
I presume it's because you forgot to specify the encoding type of your form element.
enctype="multipart/form-data"
So, by default - the browser will assume that the form encoding type is "application/x-www-form-urlencoded" which does not support files in this way. You can still securely send file binary data with the stock encoding method however, this might be where performance and functionality are determining factors to which you choose. I recommend running some tests to confirm which is the fastest. In some cases, the difference will be negligible and will likely be for sake of consistency.
Skip the FileReader API and use the file object directly:
<input type=file files-input ng-model="files" ng-change="upload()" />
The filesInput Directive
angular.module("myApp").directive("filesInput", function() {
return {
require: 'ngModel',
link: function linkFn (scope, elem, attrs, ngModel) {
elem.on("change", function (e) {
ngModel.$setViewValue(elem[0].files, "change");
});
},
};
});
The upload() function
vm.upload = function() {
//var formData = new $window.FormData();
//formData.append("file-0", vm.files[0]);
var config = { headers: { "Content-Type": undefined } };
$http.post(url, vm.files[0], config)
.then(function(response) {
vm.result = "SUCCESS";
}).catch(function(response) {
vm.result = "ERROR "+response.status;
});
};
The XHR API send() method can post either a file object or a FormData object. It is more efficient to send the file object directly as the XHR API uses base64 encoding for the FormData object which has a 33% overhead.
The DEMO on PLNKR.
To make it works, I had to do these modifications:
Directive:
myModule.directive('validFile', function() {
return {
require: 'ngModel',
link: function(scope, elt, attrs, ctrl) {
ctrl.$setValidity('validFile', elt.val() !== '');
elt.bind('change', function() {
var file = document.getElementById('uploadOT').files;
var reader = new FileReader();
reader.onload = function(e) {
scope.sendFile(file[0], scope.OT); ////CHANGE HERE
};
scope.showUploadProgress = true;
scope.filename = file[0].name;
reader.readAsArrayBuffer(file[0]); ////CHANGE HERE
ctrl.$setValidity('validFile', elt.val() !== '');
scope.$apply(function() {
ctrl.$setViewValue(elt.val());
ctrl.$render();
});
});
}
};
});
Inside Controller
$scope.sendFile = function(file, id) {
var fd = new FormData();
fd.append('id', id);
fd.append('file', file);
fd.append('MAX_FILE_SIZE', 8 * 1024 * 1024);
$http({
method: 'POST',
url: 'upload.php',
data: fd,
headers: {'Content-Type': undefined, 'Process-Data': false},
transformRequest: angular.identity
}).then( function() {
console.log('success');
}, function() {
console.log('failure');
});
};
I want to get value from file input from angularjs form in laravel, but i can't get the value.
why?
angularjs:
<div ng-controller="UploadImgController" >
<div ng-repeat="image in images">
<img ng-src="{{image.image}}" />
</div>
<form ng-submit="uploadImg()" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="path" id="path" ng-model="addimages.path" accept="image/*" app-filereader>
<input type="text" name="propertyid" ng-model="addimages.propertyid">
<input type="submit" value="Upload Image" name="submit" class="btn btn-primary" >
</form>
</div>
laravel (UploadImgController.php):
public function store()
{
$file = Input::file('path');
echo "file: ".$file;
}
(routes.php):
Route::resource('img','UploadImgController');
I got no value. What should I do? Thank you. :)
I recommend using ng-file-upload.
View
<button ng-file-select ng-model="myFiles" ng-file-change="upload($files)">Upload</button>
Angular JS
var app = angular.module('fileUpload', ['angularFileUpload']);
app.controller('MyCtrl', ['$scope', '$upload', function ($scope, $upload) {
$scope.upload = function (files) {
if (files && files.length){
for (var i = files.length - 1; i >= 0; i--) {
var file = files[i];
$upload.upload({
url: '/upload',
fields: {key: 'value'},
file: file
})
.progress(function (evt) {
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('File upload ' + progressPercentage + "% complete.");
})
.success(function (data, status, headers, config) {
console.log(data);
})
.error(function(data, status, headers, config) {
console.log(data);
});
}
}
};
}
]);
Laravel Route
Route::post('upload', [
'uses' => 'FileUploadController#upload'
]);
Laravel Controller
public function upload() {
$file = \Input::file('file');
return $file;
}
You can pull that off without a plugin actually. I did face a similar problem once and this is how I went about it.
View
<input type="file" name="file" onchange="angular.element(this).scope().uploadImage(this.files)"/>
Angularjs Controller
$scope.uploadavtar = function (files) {
var fd = new FormData();
//Take the first selected file
fd.append("file", files[0]);
$http.post("/upload-url" + $scope.school.profile.id, fd, {
withCredentials: true,
headers: {'Content-Type': undefined},
transformRequest: angular.identity
}).then(function successCallback(response) {
$scope.result = response;
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
console.log(response);
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
Routes.php
Route::post('/upload-url', 'UsersController#uploadFile');
Laravel Controller
// Upload files
public function uploadFile(Requests\UpdateuploadfileRequest $request, $id)
{
$extension = Input::file('file')->getClientOriginalExtension();
$fileName = time().'.'.$extension; // renameing image
$destination = 'uploads/img'. $fileName;
move_uploaded_file($_FILES['file']['tmp_name'], $destination);
}
}
Request validation file (UpdateuploadfileRequest.php)
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$rules = [
];
return $rules;
}