I have a canvas image generated by some JS on my page that I'm trying to upload to my server using Laravel, my controller code:
public function imageUploadAPI(Request $request)
{
$imageName = time().'.'.$request->image->getClientOriginalName();
$request->image->move('/home/XXXXX/storage/app/public/images/'.$request->project_id.'/'.$request->report_id.'/', $imageName);
return response()->json(['success'=>['You have successfully upload image.'],'image'=>[$request->project_id.'/'.$request->report_id.'/'.$imageName]]);
}
Im trying to send in as a blob but it did NOT work, any ideas?
my code:
function uploadImage() {
var canvas = document.getElementById('snapshot');
canvas.toBlob((blob) => {
const newImg = document.createElement('img');
const url = URL.createObjectURL(blob);
newImg.onload = () => {
URL.revokeObjectURL(url);
};
var formdata = new FormData($("#addForm")[0]);
formdata.append('image', url);
$.ajax({
url : "/api/image-upload",
type: "POST",
data : formdata,
processData: false,
contentType: false,
success:function(data){
console.log(data.image);
},
error:console.log('Error'),
});
});
}
One thing i know is laravel need file instance to upload image using laravel storage helpers so check if your upload is file instance or not. Here is a solution if your uploaded file is base64 and you want to change it to file instance How to convert base64 image to UploadedFile Laravel
Related
I have a custom form on a SharePoint list in which the user uploads an image and a caption.
There is a PowerPoint slide with a template where the image should then go and the caption below it. Ideally I want the uploaded image to be taken from the SharePoint list and automatically input to the PowerPoint slide with the caption. The slide should then be saved as an image file and uploaded to SharePoint picture library to enable it to be used in a picture library slideshow on the homepage.
Does anyone have any idea how to do this or any other ways in which this may be possible.
I have tried using a combination of JavaScript and html with no luck.
You can use the SharePoint REST API to retrieve the image and caption from the SharePoint list, then use the Microsoft Graph API to add the image and caption to the PowerPoint slide template. Once the slide is updated, you can use the Microsoft Graph API to convert the slide to an image file and then upload the image file to the SharePoint picture library using the SharePoint REST API. You can use a programming language such as Python or JavaScript to automate this process.
You can refer to following code to upload pic to sharepoint by rest api and js
var fileInput = jQuery('#getFile');
var file = fileInput[0].files[0];
var serverRelativeUrlToFolder = '*****'; //if the library in subsite, You have to remove the forward slash "/" before the document library relative url.
proccessUploadUsingJQueryAjax(file, serverRelativeUrlToFolder);
function getFileBuffer(file) {
var deferred = jQuery.Deferred();
var reader = new FileReader();
reader.onloadend = function (e) {
deferred.resolve(e.target.result);
}
reader.onerror = function (e) {
deferred.reject(e.target.error);
}
reader.readAsArrayBuffer(file);
return deferred.promise();
}
function addFileToFolderUsingJQueryAjax(fileName, arrayBuffer, serverRelativeUrlToFolder) {
// Construct the endpoint.
var fileCollectionEndpoint = String.format(
"{0}/_api/web/GetFolderByServerRelativeUrl('{1}')/files/add(overwrite=true, url='{2}')",
_spPageContextInfo.webAbsoluteUrl, serverRelativeUrlToFolder, fileName);
// Send the request and return the response.
// This call returns the SharePoint file.
return jQuery.ajax({
url: fileCollectionEndpoint,
type: "POST",
data: arrayBuffer,
processData: false,
contentType: "application/json;odata=verbose",
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
}
});
}
function proccessUploadUsingJQueryAjax(file, serverRelativeUrlToFolder){
var getFile = getFileBuffer(file);
getFile.done(function (arrayBuffer) {
// Add the file to the SharePoint folder.
var addFile = addFileToFolderUsingJQueryAjax("image.jpg", arrayBuffer, serverRelativeUrlToFolder);
addFile.done(function (file, status, xhr) {
alert("File Uploaded");
});
addFile.fail(function (error) { alert("Error Add File: " + error.responseText); });
});
getFile.fail(function (error) { alert("Error Get File: " + error.responseText); });
}
I have tried using some code to get blob uploaded to server, but this code has not functioned as intended. need help in finding where the error is and perhaps how to upload blob video to MySQL server.
The js code I used is
var blob = URL.createObjectURL(recorder.getBlob());
var fd = new FormData();
fd.append('fname', 'test.mp4');
fd.append('data', blob);
$.ajax({
type: 'POST',
url: '../../application/controllers/upload.php',
data: fd,
processData: false,
contentType: false
}).done(function(data) {
alert(data);
});
Then this is the PHP code I tried
foreach(array('video', 'audio') as $type) {
if (isset($_FILES["${type}-blob"])) {
echo 'uploads/';
$fileName = $_POST["${type}-filename"];
$uploadDirectory = 'uploads/'.$fileName;
if (!move_uploaded_file($_FILES["${type}-blob"]["tmp_name"], $uploadDirectory)) {
echo(" problem moving uploaded file");
}
echo($fileName);
}
}
Once I am able to get this working I can be able to insert the data into MySQL database
Thank you for helping
you placed your blob into your formdata OBJECT and called it data
fd.append('data', blob);
So when that gets to PHP is will be placed in
$_FILES['data']
Just like as if you had done
<input type="file" name="data">
I'm using javascript to get the filepath but it returns C:\fakepat\ fileName, then I replace the fakepath to get the filename only. Then ajax to php. And execute this line:
copy("filename", $targetPath);
It returns this error no directory or file.
PHP is executed on server-side, therefor it has no access to your client-side file.
To transmit the file from client to server using ajax I recommend wrapping a form around your upload-button. After submitting the XHR you can access the file in PHP via the $_FILES variable and move it where ever you want:
HTML
<form>
<input type="file" id="upload" onchange="javascript:uploadFile()" />
</form>
JS
function uploadFile() {
var formData = new FormData(); // using XMLHttpRequest2
var fileInput = document.getElementById('upload');
var file = fileInput.files[0];
formData.append("uploadfile", file);
request.send(formData);
}
PHP
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['uploadfile']['name']);
if (move_uploaded_file($_FILES['uploadfile']['tmp_name'], $uploadfile)) {
// upload succeeded
} else {
// upload failed
}
in ajax you can write this
var form_data = new FormData();
var file_data1 = $('#file').prop('files')[0];
form_data.append('file', file_data1);
$.ajax({
url: 'assets/addEdi.php', // point to server-side PHP script
dataType: 'text', // what to expect back from the PHP script, if anything
cache: false,
contentType: false,
processData: false,
data: form_data,
type: 'post',
success: function (php_script_response) {
$('#res').html(php_script_response);
}
});
#Toltis Because of the fakepath, you should upload via javascript.
This it the html:
<input type="file" id="file" onchange="upload(event)" />
<img src="" id="img" />
<textbox id="hidden_box" name="hidden_box" style="visibility: hidden;"></textbox>
Then the Js:
function upload(e) {
var input_file = document.getElementById('file');
var hidden = document.getElementById('hidden_box');
var fr = new FileReader();
fr.readAsDataURL(input_file.files[0]);
fr.onloadend = function(e) {
var img_tag = document.getElementById('img');
dataUrl = e.target.result;
img_tag = dataUrl
hidden.innerHTML = dataUrl
}
}
Then you can target the contents of the hidden box in php. Break it on the (,) and then decode the remaining string - base64_decode - and then save it to a file.
The real file name, you already know how to get it.
I am able to upload an image file to SharePoint, but it is not being recognized as an image. I have tried utilizing the following directive based on research that states images need to be base64 encoded when uploaded into SharePoint, but it still uploads a file that appears to be corrupt: https://github.com/adonespitogo/angular-base64-upload
I am happy to use this directive, but am unsure of how to pass what I need into SharePoint's REST API.
The original iteration I had does not use this directive, but is more of a straight upload attempt.
What I need to achieve is as follows:
1) Successfully upload an image without it being "corrupted", and does this require base64 encoding/how do I achieve this?
2) Upload images by their name (not "test.jpg") and have some metadata (ex. upload an image with the title or department name it belongs to)
Iteration 1: No Directive
Here is my HTML (Please note that the controller is tied to the page via ng-route):
<div class="col-md-12">
<form>
<input type="file" onchange="angular.element(this).scope().filesChanged(this)" data-ng-model="files" multiple>
<button data-ng-click="upload()">Submit</button>
<li data-ng-repeat="file in files">{{file.name}}</li>
</form>
</div>
Here is my controller:
$scope.filesChanged = function (elm) {
$scope.files = elm.files
$scope.$apply();
}
$scope.upload = function () {
var fd = new FormData()
angular.forEach($scope.files,function(file){
fd.append('file',file)
})
$http.post("/sites/asite/_api/web/lists/getByTitle('Images')/RootFolder/Files/add(url='test.jpg',overwrite='true')", fd,
{
transformRequest: angular.identity,
headers: {
'Content-Type':undefined, 'X-RequestDigest': $("#__REQUESTDIGEST").val()}
}).success(function (d) {
console.log(d);
});
}
UPDATE: I believe the issue is isolated to my $http post to SharePoint. Using the directive mentioned above, I am able to output the base64, but am unsure how to pass this into my post for upload.
Iteration 2: Using Directive
Here is my current HTML using the https://github.com/adonespitogo/angular-base64-upload directive:
<form>
<input type="file" data-ng-model="files" base-sixty-four-input>
<button data-ng-click="upload()">Submit</button>
</form>
My controller that is posting the corrupted image files to SharePoint:
$scope.upload = function () {
console.log($scope.files); // Output result from upload directive
$http({
method: 'POST',
url: "/sites/ens/_api/web/lists/getByTitle('Report Images')/RootFolder/Files/add(url='" + $scope.files.filename +"',overwrite='true')",
headers: {
'Content-Type': false ,
'X-RequestDigest': $("#__REQUESTDIGEST").val()
},
data: $scope.files,
}).success(function (data) {
console.log(data);
});
}
Update 2: Using SP.RequestExecutor as follows creates the same result. A file upload but not rendering. This happens for images and documents:
Iteration 3: Using Directive and SP.RequestExecutor
$scope.upload = function () {
var dataURL = 'data:' + $scope.files.filetype + ';' + 'base64,' + $scope.files.base64;
var createitem = new SP.RequestExecutor("/sites/asite");
createitem.executeAsync({
url: "/sites/asite/_api/web/lists/getByTitle('Images')/RootFolder/Files/add(url='" + $scope.files.filename + "')",
method: "POST",
binaryStringRequestBody: true,
body: dataURL,
success: fsucc,
error: ferr,
state: "Update"
});
function fsucc(data) {
alert('success');
}
function ferr(data) {
alert('error\n\n' + data.statusText + "\n\n" + data.responseText);
}
}
Update 3: Using .ajax as follows, it will successfully post the image, but when using $http, it corrupts the image.
Iteration 3: Using .Ajax (works)
function uploadFileSync(spWebUrl , library, filename, file)
{
var reader = new FileReader();
reader.onloadend = function(evt)
{
if (evt.target.readyState == FileReader.DONE)
{
var buffer = evt.target.result;
var completeUrl = spWebUrl
+ "/_api/web/lists/getByTitle('"+ library +"')"
+ "/RootFolder/Files/add(url='"+ filename +"',overwrite='true')?"
+ "#TargetLibrary='"+library+"'&#TargetFileName='"+ filename +"'";
$.ajax({
url: completeUrl,
type: "POST",
data: buffer,
async: false,
processData: false,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"content-length": buffer.byteLength
},
complete: function (data) {
//uploaded pic url
console.log(data.responseJSON.d.ServerRelativeUrl);
$route.reload();
},
error: function (err) {
alert('failed');
}
});
}
};
reader.readAsArrayBuffer(file);
}
Iteration 4: Using $http (corrupts image)
function uploadFileSync(spWebUrl , library, filename, file)
{
var reader = new FileReader();
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) {
var buffer = evt.target.result;
var completeUrl = spWebUrl
+ "/_api/web/lists/getByTitle('" + library + "')"
+ "/RootFolder/Files/add(url='" + filename + "',overwrite='true')?"
+ "#TargetLibrary='" + library + "'&#TargetFileName='" + filename + "'";
$http({
url: completeUrl,
method: "POST",
data: buffer,
processData: false,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"content-length": buffer.byteLength
}
}).success(function (data) {
//uploaded pic url
//console.log(data.responseJSON.d.ServerRelativeUrl);
$route.reload();
}).error(function (err) {
alert(err);
});
}
};
reader.readAsArrayBuffer(file);
}
Yes, you must do the base64 encoding.
Following this article, your filesChanged will be function for base64 encoding:
$scope.filesChanged = function (input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
//Sets the Old Image to new New Image
$('#photo-id').attr('src', e.target.result);
//Create a canvas and draw image on Client Side to get the byte[] equivalent
var canvas = document.createElement("canvas");
var imageElement = document.createElement("img");
imageElement.setAttribute('src', e.target.result);
canvas.width = imageElement.width;
canvas.height = imageElement.height;
var context = canvas.getContext("2d");
context.drawImage(imageElement, 0, 0);
var base64Image = canvas.toDataURL("image/jpeg");
//Removes the Data Type Prefix
//And set the view model to the new value
$scope.data.Photo = base64Image.replace(/data:image\/jpeg;base64,/g, '');
}
//Renders Image on Page
reader.readAsDataURL(input.files[0]);
}
};
My advice to you is also to change ng-model from $scope.files to $scope.data.Photo to avoid problems with scope and add an id in your input tag. (in this case id="photo-upload")
So, your HTML for upload will look like:
<input type="file" onchange="angular.element(this).scope().filesChanged(this)" data-ng-model="data.Photo" id="photo-upload" multiple>
And for representing your uploaded pic, in your case, you can use this:
<img ng-src="data:image/jpeg;base64,{{data.Photo}}" id="photo-id"/>
I'm just not sure for multiple upload, but for single upload it works great for me.
Hope this will help you to solve your problem with SharePoint.
Good luck!
I dynamically generate svg markup on client side and convert it to a data-url for downloading purposes. This procedure works fine and generates a valid svg file.
Besides I have a Java Servlet which takes an uploaded svg file and converts it to pdf. When I take a downloaded svg file from above and upload it through a standard HTML form this Servlet works absolutely fine.
I just want to combine those two parts by sending the generated svg without even saving it before. I already tried to send the data as base64 string like that:
reader.readAsDataURL(blob);
reader.onloadend = function() {
base64data = reader.result;
console.log(base64data );
form['data'].value = base64data;
form.submit();
}
But this doesn't seem to work. Are there any ways of emulating a file upload with JavaScript?
You should use FormData object:
$('form').submit(function(){
/**** creating blob object
.....
****/
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
base64data = reader.result;
var fd = new FormData(this);
fd.append('file', base64data, 'file_data'); // field_data - "Optional" param, it means The filename reported to the server
fd.append('other_field', fieldvalue);
$.ajax({
type: 'POST',
url: '/upload.php',
data: fd,
processData: false,
contentType: false
}).done(function(data) {
console.log(data);
});
}
});