Upload video with edge slingshot meteor - javascript

I try to upload a video on my s3 bucket with edge:slingshot package, It's work fine with image file but with video file I have this error : "Error: Failed to upload file to cloud storage [ - 0] trace : Meteor.makeErrorType/errorClass#http://localhost:3000/packages/meteor.js?9730f4ff059088b3f7f14c0672d155218a1802d4:525:15
getError#http://localhost:3000/packages/edgee_slingshot.js?4c5b8e7dc4cae9d464984ead4903ef4beaac99f5:388:1
Slingshot.Upload/<.transfer/<#http://localhost:3000/packages/edgee_slingshot.js?4c5b8e7dc4cae9d464984ead4903ef4beaac99f5:407:18"
my template event :
Template.upload_vid.events({
'change input[type="file"]': function ( event, template ) {
var file = event.currentTarget.files[0];
Modules.client.uploadToAmazonS3( { file: file, template: template, type :"video" } );
}});
my template :
<template name="upload_vid">
<input type="file" name="file" id="file_vid">
<label for="file_vid">download</label>
</template>
my function to define slingshot (slingshot.js on server side only):
Slingshot.fileRestrictions( "uploadVidToAmazonS3", {
allowedFileTypes: [ "video/webm", "video/mp4", "video/mov", "video/3gp"],
maxSize: 50 * 1024 * 1024
});
Slingshot.createDirective( "uploadVidToAmazonS3", Slingshot.S3Storage, {
bucket: my_bucket,
acl: "public-read",
authorize: function () {
var user = Meteor.userId();
if(user){
return true;
} else {
return false;
}
},
key: function ( file ) {
var user = Meteor.users.findOne( this.userId );
return user.emails[0].address + "/video_profil/" + file.name;
}
});
and function for use Slingshot and make upload (work fine with image) :
let template;
let _uploadPicsToAmazon = ...
let _uploadVidToAmazon = ( file, type ) => {
var uploader = new Slingshot.Upload( "uploadVidToAmazonS3" );
uploader.send( file, ( error, url ) => {
if ( error ) {
console.log( error, "warning" );
} else {
console.log("success");
}
});
};
let upload = ( options ) => {
template = options.template;
let file = options.file;
let type = options.type;
if(type == "img"){
_uploadPicsToAmazon( file, type );
}else{
_uploadVidToAmazon( file, type );
}
};
Modules.client.uploadToAmazonS3 = upload;
anyone have a solution? thank you beforehand.

Related

How to change file reference strings to use generated hashes from copy file webpack plugin

I'm copying all my assets to my build directory using copy webpack plugin. It generates all the files with the hashes properly but is there a simple way of changing any of these file references in code with the new hashed filename?
new CopyWebpackPlugin({
patterns: [
{ from: 'src/assets', to: '[path][name].[contenthash][ext]' },
],
}),
Im currently using strings like below to load assets into phaser, using a query param to break the cache but i want the url to be updated with the new hash filename so I don't need to use the query param to bust the server cache and can take advantage of server caching.
{
key: 'atlas',
url: `assets/img/atlas.json?t=${new Date().getTime().toString()}`,
path: './assets/img/'
},
{
key: 'atlas',
url: `assets/img/atlas.json`,
path: './assets/img/'
},
so Im hoping the above will look like this in the output after webpack has run
{
key: 'atlas',
url: `assets/img/atlas.{generatedHash}.json`,
path: './assets/img/'
},
Edit:
Okay so I accomplished the above by using webpack-asset-manifest
new ManifestPlugin({
// publicPath: 'assets/',
}),
and then having a function for getting my urls from the generated json after it is loaded
protected getAssetFromKey(key: string | Array<string>): string | Array<string> {
if (Array.isArray(key)) {
let urls = new Array<string>();
key.forEach((urlKey: string) => {
urls.push(this.assetKeys[urlKey]);
});
return urls;
} else {
return this.assetKeys[key];
}
}
But now I have hit an issue where the json atlas files are pointing to the old images and there seems to be no easy way to edit these. Im thinking of something like string replace loader but Im wondering if there is a better way and I am unsure of how to replace the string with a value from the manifest.json that is exported by webpack.
Okay So I figured this out by adding the manifest plugin to my webpack config which generates a json file with all the original file names as keys and all the new hashed filenames as values.
new ManifestPlugin({
}),
and then I added in a compiler hook in the plugins area that does reads all the atlas files and replaces the strings in them, as well as any references to the assets in the compiled code.
https://webpack.js.org/api/compiler-hooks/
{
apply: (compiler) => {
compiler.hooks.done.tap("update links", (stats) => {
Fs.readJson('dist/assets-manifest.json').then( (value) => {
let keys = Object.keys(value)
let files = Object.values(value);
files.forEach( (file, index) => {
if( file.includes('json')) {
let splitString = keys[index].split('/');
let findFile = splitString[splitString.length-1].replace('.json', '');
console.log(`find file- ${findFile}`);
let replaceWithString = '';
let replaceString = ''
for( let i =0 ; i < keys.length; i++) {
if( keys[i].includes(`${findFile}`) && keys[i].includes('.webp') ) {
console.log(keys[i]);
let splitFiles = files[i].split('/');
let splitKeys = keys[i].split('/');
replaceWithString = splitFiles[splitFiles.length-1];
replaceString = splitKeys[splitKeys.length-1];
break;
}
}
console.log( `REPLACE WITH STRING = ${replaceWithString}`)
console.log(`reading file-${file}`);
Fs.readJson(`dist/${file}`).then( (val) => {
let stringJson = JSON.stringify(val);
console.log(`replacing ${replaceString} with ${replaceWithString}`);
let result = stringJson.replace(replaceString, replaceWithString);
let outputJson = JSON.parse(result);
Fs.writeJson(`dist/${file}`, outputJson, 'utf8').then( () => {
console.log( `!!!!! SUCCESS !!!!!`);
});
});
}
});
files.forEach( (file) => {
if( file.includes('.js') && !file.includes('json') ) {
console.log('FILE: ' + file)
Fs.content(`dist/${file}`).then( ( val) => {
keys.forEach( (key,index) => {
if( key.includes('assets/')) {
val = val.replaceAll(key, files[index]);
console.log(`REPLACING: ${key} with ${files[index]} in ${file}`)
}
});
Fs.writeFile(`dist/${file}`, val).then( () => {
console.log("--SUCCESS---")
});
});
}
})
}).catch( (err) => {
console.log(`error ${err}`);
})
});
}
},

how to access props in react quill image handler

i am using react quill editor for my project and using my backend server to image upload but i need to access props inside the image handler of react quill and i am unable to do so as not able to access this object inside image handler.
here is my editor code.
<ReactQuill
ref={(el) => (this.quillRef = el)}
onChange={this.handleChange}
placeholder={"share your thoughts"}
modules={{
toolbar: {
container: [
[{ header: "1" }, { header: [2, 3, 4, 5, 6] }, { font: [] }],
[{ size: ["small", false, "large", "huge"] }],
["bold", "italic", "underline", "strike", "blockquote"],
[{ list: "ordered" }, { list: "bullet" }],
["link", "image", "video"],
["clean"],
["code-block"],
[{ color: [] }, { background: [] }], // dropdown with defaults from theme
[{ align: [] }],
],
handlers: {
image: this.imageHandler,
},
},
}}
/>;
function imageHandler() {
let self = this;
let image;
let image_extension;
const Cryptr = require("cryptr");
const cryptr = new Cryptr(key);
const users = localStorage.getItem("users")
? JSON.parse(cryptr.decrypt(localStorage.getItem("users")))
: {};
// console.log(users[users.lastLoginId])
let loggedinUser = users[users.lastLoginId];
const input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/*");
input.setAttribute("class", "Editor-mage");
input.click();
input.onchange = async () => {
//debugger
const file = input.files[0];
var ValidImageTypes = [
"image/gif",
"image/jpeg",
"image/png",
"image/jpg",
"image/GIF",
"image/JPEG",
"image/PNG",
"image/JPG",
];
let file_type = file.type;
let filename = file.name;
let extension = filename.split(".").pop();
if (ValidImageTypes.indexOf(file_type) >= 0) {
if (true) {
var fileToLoad = file;
loadImage(
fileToLoad,
(canvas) => {
if (canvas) {
// this.setState({
image = canvas.toDataURL();
image_extension = extension;
//});
const res = new Promise(function (resolve, reject) {
axios({
method: "post",
url: API_URL + "api/v1/postblogimage",
headers: {
"x-access-handler": loggedinUser.token,
},
data: {
image: image,
image_extension: image_extension,
userid: loggedinUser.userid,
},
})
//axios.post(API_URL + 'api/v1/postblogimage', formData, config)
.then((response) => {
//debugger
if (
response.data.error == "false" ||
response.data.error == false
) {
if (
response.data.status == 200 &&
response.data.message == "Image uploaded successfully"
) {
//debugger
const range = self.quill.getSelection(true);
// Insert temporary loading placeholder image
// this.quill.insertEmbed(range.index, 'image', `${window.location.origin}/images/loaders/placeholder.gif`);
// Move cursor to right side of image (easier to continue typing)
self.quill.setSelection(range.index + 1);
// Remove placeholder image
self.quill.deleteText(range.index, 1);
// Insert uploaded image
let url = response.data.data[0].imageURL;
self.quill.insertEmbed(range.index, "image", url);
self.quill.pasteHTML(
range.index,
<img
src={url}
class="blog-image-content"
alt="Responsive image"
/>
);
}
}
// }
})
.catch((error) => {
// reject(Error("It broke"));
});
});
}
},
{ orientation: true }
);
} else {
// this.setState({
// image_warning:'File size larger than maximum allowed limit',
image = "";
image_extension = "";
// })
this.fileInput.value = "";
}
} else {
}
};
}
can someone please help me out with this one as i am stuck for long on this.
any help and suggestion will be greatly appreciated.
I read the documentation of Quilljs.
Handler functions will be bound to the toolbar (so using this will refer to the toolbar instance) and passed the value attribute of the input if the corresponding format is inactive, and false otherwise. Adding a custom handler will overwrite the default toolbar and theme behavior.
and found out the imageHandler will be called in the context of the toolbar, so this.props will not work as intended when it is called.
so to achieve the accesss to props , you can do something like this:
handlers: {
image: (val) => this.imageHandler({ val, componentProps: this.props });
}
In the imageHandler you can access it like this:
function imageHandler({ val, componentProps }) {
// componentProps has all your propss, try to print it and see
// rest of your code, instead of this.props.something take componentProps.something
}
Let me know if it helps. Thanks
I think you can use higher order function.
image: this.imageHandler(props)
...
function imageHandler(props) {
return function() {
let self = this;
let image;
...
}
}

Multiple file upload using Laravel & Vue JS

so I've been trying to upload multiple image file using Vue JS with Laravel at server side.
My template vue
<input type="file" id = "file" ref="file" v-on:change="onImageChange" multiple />
My Javascript code
<script>
export default {
data(){
return{
product: {},
image: '',
}
},
created() {
let uri = `/api/product/edit/${this.$route.params.id}`;
this.axios.get(uri).then((response) => {
this.product = response.data;
});
},
methods:{
onImageChange(e){
let files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
},
createImage(file){
let reader = new FileReader();
let vm = this;
reader.onload = (e) => {
vm.image = e.target.result;
};
reader.readAsDataURL(file);
},
replaceByDefault(e) {
e.target.src = this.src='/uploads/products/default_image.jpg';
},
saveImage(e){
e.preventDefault()
var file = document.getElementById('file').files;
let formData = new FormData;
formData.append('productId', this.product.id)
formData.append('file', file[0])
axios.post('/api/product/image/add', formData, {
headers: {'Content-Type': 'multipart/form-data'}
}).then((response) => {
this.$router.push({name: 'view',params: { id: this.product.id }});
});
}
}
}
</script>
I saw somewhere the internet that in vue you can use looping the formData.append but how do i catch the data in the server side. Here is my ProductController
$saveImage = new Gallery;
$saveImage->product_id = $request->productId;
$file = request()->file('file');
$file_name = time().$file->getClientOriginalName();
$path = $imgUpload = Image::make($file)->save(public_path('/uploads/products/' . $file_name));
$saveImage->path = '/uploads/products/'.$file_name;
$saveImage->status = 1;
$saveImage->save();
return "success";
Thank you very much guys!
you can use request()->file('file') to get files. but you have to add some changes in your vue source when you are trying to send an array of files.
Vue
let formData = new FormData;
formData.append('productId', this.product.id)
// append files
for(let i=0; i<file.length; i++){
formData.append('file[]', file[i])
}
useing file[] instead of file will generate an array of files in request payload.
then in laravel side of code you can use request()->file('file') to get that array of files. but if you want just one of them (for example: first one) you can use request()->file('file.0') to get that file.

Upload file with Primeng upload component

I would upload the file in Angular using upload component
Here's my HTML:
<p-fileUpload mode="basic" name="demo[]" customUpload="true" accept="image/*" maxFileSize="1000000" (uploadHandler)="upload($event)"></p-fileUpload>
in my ts I print param value
upload(event) {
console.log(event)
}
I get only metadata and not blob content
{"files":[{"objectURL":{"changingThisBreaksApplicationSecurity":"blob:https://prime-ng-file-uploading.stackblitz.io/d429e761-c391-45fa-8628-39b603e25225"}}]}
I would also get file content to send via API to the server
Here's a stackblitz demo
In the official documentation you have an example:
export class FileUploadDemo {
uploadedFiles: any[] = [];
constructor(private messageService: MessageService) {}
onUpload(event) {
for (let file of event.files) {
this.uploadedFiles.push(file);
}
this.messageService.add({
severity: 'info',
summary: 'File Uploaded',
detail: ''
});
}
}
When I used primeNG, I did it like this (for uploading only 1 file) :
HTML
<p-fileUpload name="myfile[]" customUpload="true" multiple="multiple" (uploadHandler)="onUpload($event)" accept="application/pdf"></p-fileUpload>
component.ts
export class AlteracionFormComponent {
uplo: File;
constructor(private fileService: FileUploadClientService) {}
onUpload(event) {
for (let file of event.files) {
this.uplo = file;
}
this.uploadFileToActivity();
}
uploadFileToActivity() {
this.fileService.postFile(this.uplo).subscribe(data => {
alert('Success');
}, error => {
console.log(error);
});
}
}
And my service (in Angular)
service.ts
postFile(id_alteracion: string, filesToUpload: FileUploadModel[], catalogacion: any): Observable<any> {
let url = urlAPIAlteraciones + '/';
url += id_alteracion + '/documentos';
const formData: FormData = new FormData();
formData.append('json', JSON.stringify(catalogacion));
for (let file of filesToUpload) {
formData.append('documento', file.data, file.data.name);
}
console.log(formData);
let headers = new HttpHeaders();
return this._http.post(url, formData, { headers: headers });
}
Hope that helps
I'm trying to use the standard PrimeNG approach for uploading multiple files at once.
<p-fileUpload name="myfile[]" [url]="MyApiUrl" multiple="multiple"></p-fileUpload>
In my ApiController, I get the following:
public List<FileModel> Post()
{
var files = HttpContext.Current.Request.Files;
var result = new List<FileModel>();
if (files.Count > 0)
{
Guid guid = Guid.NewGuid();
var path = System.IO.Path.Combine(System.Web.Configuration.WebConfigurationManager.AppSettings["UploadFileLocation"], guid.ToString() + "/");
System.Web.HttpContext.Current.Session["guid"] = guid;
if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); }
foreach (string fileName in files.AllKeys)
{
var file = files[fileName];
var filePath = path + file.FileName;
file.SaveAs(filePath);
result.Add(_data.InsertFile(FileModel.Create(path, file.FileName)));
}
}
return result;
}
The problem I'm having is that "fileName" in var file = files[fileName] always equals the first file in the group of files uploaded. I don't know if this is an issue with HttpContext.Current.Request.Files or a PrimeNG bug. Has anyone ran into this type of problem?
Doing it this way because I want to store the guid in my session and grab it later on when the form is submitted...

How to get mimeType from Cordova File Transfer Plugin?

I am developing hybrid mobile application.
In one of the scenario we need to fetch mimeType from a file when we select or upload a file.
I am using apache FileTransfer.
window.resolveLocalFileSystemURL(fileURI , resolveOnSuccess, resolveOnFail)
you can get it from cordova File plugin.
$cordovaFile.checkFile(uri, '')
.then(function(entry) {
// success
var name = entry.name;
entry.file(function(data) {
// get mime type
var mime = data.type;
alert(mime);
})
}, function(error) {
// error
// show toast
});
I got it working like this in TypeScript and Angular 2:
this._File.resolveLocalFilesystemUrl(somefileUri).then((entry: Entry) => {
if (entry) {
var fileEntry = entry as FileEntry;
fileEntry.file(success => {
var mimeType = success.type;
}, error => {
// no mime type found;
});
}
});
file-transfer does not expose mimeType and other FileUploadOptions params.
Mimetype autodetection is only supported for uploads in Windows plugin code.
And here is a Jira ticket for this feature CB-5946 - it also has some suggestions on Android implementation.
In Angular 2 I use this:
export class Plugins {
albums = {
open () : Promise<any> {
return ImagePicker.getPictures({
quality: 100,
maximumImagesCount: 1,
}).then((imgUrls) => {
return imgUrls;
}, (err) => {
if(err.error == "cordova_not_available") {
alert("Cordova is not available, please make sure you have your app deployed on a simulator or device");
} else {
console.log("Failed to open albums: " + err.error);
}
});
},
}
...
#Component({
templateUrl: 'build/pages/home/home.html',
directives: [UploadButton]
})
export class HomePage implements OnInit {
openAlbums = (): void => {
var $self = this;
this._plugins.albums.open().then((imgUrls) => {
imgUrls.forEach((imageUrl: string): void => {
if (imageUrl) {
window.resolveLocalFileSystemURL(imageUrl, function (entry: FileEntry) {
entry.file(file=> {
console.log('mimeType', file.type);
}, ((error:FileError) => console.log(error)));
});
}
});
}); };
resolveLocalFileSystemURL gives back through the success callback an Entry which I had to cast to FileEntry to get access to the file method which gives back a File which extends Blob that has the mime type property.

Categories