Mobile Safari video upload makes site refresh - node.js

I created a photo uploading server on a raspberry pi using Angular with Node.Js and multer. This is all hosted on an unsecured ad-hoc network created by the pi itself. The reason I am going for ad-hoc here is because I want to be able to take this on road trips and store photos on it wherever I may be. When I use any mobile browser on my iPhone to upload a video longer than 15 seconds or select a large amount of photos it stalls for a second then refreshes the page which stops the upload. As for error messages I could not see any on Desktop or mobile as the page retunrs with "Something went wrong while displaying webpage" Is there a way to increase multers file size limit? Safari iOS refresh
HTML for Upload:
<div class="dropzone">
<input type="file" #fileDropRef id="fileDropRef" multiple (change)="handleDrop($event)">
<img src="../../assets/upload.png">
<p>Drag and drop here</p>
<p>or</p>
<p>browes for file</p>
</div>
<div id="progressBar" #progressBar></div>
<div id="photoAlbum" #photoAlbum></div>
<div id="gallery" #gallery></div>
And to handle the upload
handleDrop(e) {
e.preventDefault()
e.stopPropagation()
console.log(e)
this.handleFiles(e.target.files)
}
initializeProgress(numFiles) {
this.progressBar.nativeElement.value = 0
this.uploadProgress = []
for(let i = numFiles; i > 0; i--) {
this.uploadProgress.push(0)
}
}
handleFiles(files) {
files = [...files]
this.initializeProgress(files.length)
files.forEach(this.uploadFile)
files.forEach(this.previewFile)
}
uploadFile(file, i) {
var formData = new FormData();
formData.append("photos", file);
formData.append("photos", localStorage.getItem('email'));
var content = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
var blob = new Blob([content], { type: "text/xml"});
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE) {
console.log(request.responseText);
}
}
request.open("POST", 'http://localhost:port/api/mov/uploadmedia');
request.send(formData);

In case anyone comes across this. The problem I was facing was that I was caching a video that surpassed the browser cache limit. To avoid caching I simply used an XMLHttpRequest to upload the file immediately after it is selected. This will stream the file directly to the disk.
counter(e) {
if(this.i != e.target.files.length){
this.i++;
this.handleDrop(e)
}
}
handleDrop(e) {
e.preventDefault()
e.stopPropagation()
console.log(e)
var formData = new FormData();
formData.append("photos", e.target.files[this.i]);
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if(request.readyState == XMLHttpRequest.DONE) {
console.log(request.responseText)
}
}
request.open("POST", 'http://localhost:port/api/mov/uploadmedia')
request.send(formData)
this.counter(e)
}

Related

How to send Blob image to NodeJs using Angular2?

I am having problems trying to upload a photo from my frontend.
I have an input file where I can select a file from my computer.
What I want It is send that photo to my backend and store it as a Blob.
First I try to get the file and save as Blob:
foto: Blob;
setFoto(event){
this.foto = event.target.files[0];
}
But I don't know if this It is correct.
Second I send "this.foto" to the server using HTTP post and save in my db as blob. I think that my problem is that i am not sending the correct information about the photo.
In resume, what I want is send an image that I select from my computer to the server but I am having problems getting the correct information of the photo.
Solution founded
First, here is my input:
<input type="file" (change)="setFoto($event)">
Second, here is the method that you call when you select a photo.
setFoto(event) {
const foto = new Blob([event.target.files[0]]);
var reader = new FileReader();
reader.readAsDataURL(foto);
reader.onloadend = () => {
this.foto = reader.result;
}
}
this.foto is a string.
Then when i click on update button i send the new photo as url and save it in my db (Mysql) as TEXT.
updateApuesta() {
this.userService.updateBet(this.url, {
id: this.userService.getIdbet(),
coste: this.coste,
beneficio: this.beneficio,
foto: this.foto
}).subscribe(this.success.bind(this), this.error);
}
When I try to get the photo from my server I use this. I call my http get service and get the photo.
First, the new image is a
image: SafeResourceUrl;
and I assign the dat that I got from my server.
this.image = this.sanitizer.bypassSecurityTrustResourceUrl(data.foto);
You have to import:
import { DomSanitizer, SafeResourceUrl } from '#angular/platform-browser';
and pass it to your constructor:
constructor(private sanitizer:DomSanitizer ) { }
So finally, you got your image in this.image that is a SafeResourceUrl type. To load it in a you have to do this:
<img [src]="bet.foto"/>
where in your case bet.foto will be yout this.image that you have to pass to the template.
this.userService.updateBet(
this.url,{foto:this.foto}).subscr‌​ibe(this.success.bin‌​d(this), this.error);
and the service is:
updateBet(url, body) {
return this.httpRequest.put(url, body, this.options);
}
put(url, body, options) {
return this.http.put(url, body, this.setOptions(options))
.map(this.extractData)
.catch((error: any) => Observable.throw(error.json().error || 'Server error')); //Show errors if any
}
But what i said, i think i am not sending the correct info about the photo.

How add file into p:fileUpload [duplicate]

How can I set the value of this?
<input type="file" />
You cannot set it to a client side disk file system path, due to security reasons.
Imagine:
<form name="foo" method="post" enctype="multipart/form-data">
<input type="file" value="c:/passwords.txt">
</form>
<script>document.foo.submit();</script>
You don't want the websites you visit to be able to do this, do you? =)
You can only set it to a publicly accessible web resource as seen in this answer, but this is clearly not the same as a client side disk file system path and it's therefore useless in that context.
You can't.
The only way to set the value of a file input is by the user to select a file.
This is done for security reasons. Otherwise you would be able to create a JavaScript that automatically uploads a specific file from the client's computer.
Not an answer to your question (which others have answered), but if you want to have some edit functionality of an uploaded file field, what you probably want to do is:
show the current value of this field by just printing the filename or URL, a clickable link to download it, or if it's an image: just show it, possibly as thumbnail
the <input> tag to upload a new file
a checkbox that, when checked, deletes the currently uploaded file. note that there's no way to upload an 'empty' file, so you need something like this to clear out the field's value
You can't. And it's a security measure. Imagine if someone writes JS that sets file input value to some sensitive data file?
I have write full example for load URL to input file, and preview
you can check here
1
https://vulieumang.github.io/vuhocjs/file2input-input2file/
in short you can use this function
function loadURLToInputFiled(url){
getImgURL(url, (imgBlob)=>{
// Load img blob to input
// WIP: UTF8 character error
let fileName = 'hasFilename.jpg'
let file = new File([imgBlob], fileName,{type:"image/jpeg", lastModified:new Date().getTime()}, 'utf-8');
let container = new DataTransfer();
container.items.add(file);
document.querySelector('#file_input').files = container.files;
})
}
// xmlHTTP return blob respond
function getImgURL(url, callback){
var xhr = new XMLHttpRequest();
xhr.onload = function() {
callback(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
As everyone else here has stated: You cannot upload just any file automatically with JavaScript.
HOWEVER! If you have access to the information you want to send in your code (i.e., not C:\passwords.txt), then you can upload it as a blob-type, and then treat it as a file.
What the server will end up seeing will be indistinguishable from someone actually setting the value of <input type="file" />. The trick, ultimately, is to begin a new XMLHttpRequest() with the server...
function uploadFile (data) {
// define data and connections
var blob = new Blob([JSON.stringify(data)]);
var url = URL.createObjectURL(blob);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'myForm.php', true);
// define new form
var formData = new FormData();
formData.append('someUploadIdentifier', blob, 'someFileName.json');
// action after uploading happens
xhr.onload = function(e) {
console.log("File uploading completed!");
};
// do the uploading
console.log("File uploading started!");
xhr.send(formData);
}
// This data/text below is local to the JS script, so we are allowed to send it!
uploadFile({'hello!':'how are you?'});
So, what could you possibly use this for? I use it for uploading HTML5 canvas elements as jpg's. This saves the user the trouble of having to open a file input element, only to select the local, cached image that they just resized, modified, etc.. But it should work for any file type.
the subject is very old but I think someone can need this answer!
<input type="file" />
<script>
// Get a reference to our file input
const fileInput = document.querySelector('input[type="file"]');
// Create a new File object
const myFile = new File(['Hello World!'], 'myFile.txt', {
type: 'text/plain',
lastModified: new Date(),
});
// Now let's create a DataTransfer to get a FileList
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);
fileInput.files = dataTransfer.files;
</script>
You need to create a DataTransfer and set the .files property of the input.
const dataTransfer = new DataTransfer();
dataTransfer.items.add(myFile);//your file(s) reference(s)
document.getElementById('input_field').files = dataTransfer.files;
Define in html:
<input type="hidden" name="image" id="image"/>
In JS:
ajax.jsonRpc("/consulta/dni", 'call', {'document_number': document_number})
.then(function (data) {
if (data.error){
...;
}
else {
$('#image').val(data.image);
}
})
After:
<input type="hidden" name="image" id="image" value="/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8U..."/>
<button type="submit">Submit</button>
Actually we can do it.
we can set the file value default by using webbrowser control in c# using FormToMultipartPostData Library.We have to download and include this Library in our project. Webbrowser enables the user to navigate Web pages inside form.
Once the web page loaded , the script inside the webBrowser1_DocumentCompleted will be executed.
So,
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
FormToMultipartPostData postData =
new FormToMultipartPostData(webBrowser1, form);
postData.SetFile("fileField", #"C:\windows\win.ini");
postData.Submit();
}
Refer the below link for downloading and complete reference.
https://www.codeproject.com/Articles/28917/Setting-a-file-to-upload-inside-the-WebBrowser-com

Grab file from chrome webRequest onBeforeRequest

I am trying to fetch the files that want to be uploaded via POST.
Unfortunately i only get the requestBody as FormData giving me huge headaches accessing the file. I only get the filename as string.... I would like to have the file contents as blob or data-url...
//in a form on a page
<input type="file" name="files[]" multiple>
//extension's background.js
chrome.webRequest.onBeforeRequest.addListener( function(details) {
console.log(details);
n = "files[]";
var file = details.requestBody.formData[n][0];
console.log(file ); // BabyGnuTux-Big.jpg
console.log(typeof file); // string
},
{urls: ["*://example.de/*"]},
["blocking", "requestBody"]);

AJAX Image upload with backbone.js node.js and express

So I have been trawling the net for a day now trying to find a complete example of how to upload an image along with a normal POST (create) request from a backbone model. So after some initial digging around I discovered the FileReader api in HTML5 - After some testing I had this working great outside backbone by creating a XMLHttpRequest()
The problem im now trying to solve is how can I make bacbone send the FILES data along with the POST request like you would experience in a normal multipart form work flow. Im pretty new to backbone so please forgive any obvious errors. Heres what I have so far.
model
define(
[
'backbone'
],
function (Backbone) {
var Mock = Backbone.Model.extend({
url: '/api/v1/mocks',
idAttribute: '_id',
readFile: function(file){
var reader = new FileReader();
self = this;
reader.onload = (function(mockFile){
return function(e){
self.set({filename: mockFile.name, data: e.target.result});
};
})(file);
reader.readAsDataURL(file);
}
});
return Mock;
}
);
view
define(
[
'jquery',
'backbone',
'underscore',
'text!../templates/create_mock-template.html',
'models/mock',
'collections/mocks'
],
function ($, Backbone, _, createMockTemplate, Mock, mocksCollection) {
var CreateMockView = Backbone.View.extend({
template: _.template(createMockTemplate),
events: {
'submit form': 'onFormSubmit',
'click #upload-link': 'process',
'change #upload': 'displayUploads'
},
initialize: function () {
this.render();
return this;
},
render: function () {
this.$el.html(this.template);
},
process: function(e){
var input = $('#upload');
if(input){
input.click();
}
e.preventDefault();
},
displayUploads: function(e){
// Once a user selects some files the 'change' event is triggered (and this listener function is executed)
// We can access selected files via 'this.files' property object.
var formdata = new FormData();
var img, reader, file;
var self = this;
for (var i = 0, len = e.target.files.length; i < len; i++) {
file = e.target.files[i];
if (!!file.type.match(/image.*/)) {
if (window.FileReader) {
reader = new FileReader();
reader.onloadend = function (e) {
self.createImage(e.target.result, e);
};
self.file = file;
reader.readAsDataURL(file);
}
}
}
},
createImage: function(source, fileobj) {
var image = '<img src="'+source+'" class="thumbnail" width="200" height="200" />'
this.$el.append(image);
},
onFormSubmit: function (e) {
e.preventDefault();
// loop through form elements
var fields = $(e.target).find('input[type=text], textarea');
var data = {};
// add names and vlaues to data object
$(fields).each(function(i, f) {
data[$(f).attr('name')] = $(f).attr('value');
});
// create new model from data
var mock = new Mock(data);
// this should set the filename and data attributes on the model???
mock.readFile(this.file);
// save to the server
mock.save(null, {
wait: true,
error: function(model, response) {
console.log(model)
},
success: function(model, response) {
mocksCollection.add(model);
console.log(model, response);
}
});
},
});
return CreateMockView;
}
);
I totally appreciate this may all be a bit hand wavey, its more a proof of concept than anything else and a good chance to learn backbone too. So the crux of my question is this
When the request is sent by backbone to the api why arent I seeing the data and filename attrs in the request to the node/express server
Is what im trying to do even possible, I basically thought i'd be able to read the data attr and create and image on the server?
Is there a way to perhaps overide the sync method on the Mock model and create a properly formed request where POST and FILES are correctly set.
Im sure this is possible but I just cant seem to find the bit of info I need to plough on and get this working.!
Hope someone can help!
CHEERS
edit
Just wanted to provide a bit more info as by my understanding and some brief chats on the document cloud irc channel this should work. So when I call
mock.readFile(this.file)
the fileName and data attributes dont seem to get set. In fact a console log here dosent even seem to fire so im guessing this could be the problem. I would be happy with this approach to basically build up the Image on the node end based on the value of data and fileName. So why arent these properties being set and passed along in the post request to the api?
I have resolved this situation splitting the Model creation in two steps:
Basic information
Assets
For example if my Model is a Film, I show a create-form that only include title and synopsis. This information is sent to the server and create the Model. In the next step I can show the update-form and now is very easier to use File Uploads plugins like:
jQuery File Upload Very profesional and stable
BBAssetsUpload Very beta, but based on Backbone, and you can say you know the programmer ;P
You can also check their source code for references to try to achieve a one-step Backbone Model with File creation solution.
jquery-file-upload-middleware for express is probably worth mentioning.

How to upload a file (attachment) from the browser?

I don't get attachment upload for the browser to work.
Some hints are here, others there. The docs are quite good but I'm unable to translate that to a AJAX upload.
I'm looking for a super simple HTML/JavaScript example (with or w/o jQuery) of how to upload a file from (relatively modern) browser to the db without making use of jquery.couch.app.js wrapper or stuff. The simpler the besser.
Any help appreciated.
Alright, here's your pure JavaScript file upload implementation.
The basic algorithm is like this:
Get the file from the file input element
Get the file name and type off the file object
Get the latest document revision of the document you want to attach the file to
Attach the file to document using the fetched revision
The HTML part basically consists of a simple form with two elements, an input of type file and a button of type submit.
<form action="/" method="post" name="upload">
<input type="file" name="file" />
<button type="submit" name="submit">Upload</button>
</form>
Now to the JavaScript part.
window.onload = function() {
var app = function() {
var baseUrl = 'http://127.0.0.1:5984/playground/';
var fileInput = document.forms['upload'].elements['file'];
document.forms['upload'].onsubmit = function() {
uploadFile('foo', fileInput.files[0]);
return false;
};
var uploadFile = function(docName, file) {
var name = encodeURIComponent(file.name),
type = file.type,
fileReader = new FileReader(),
getRequest = new XMLHttpRequest(),
putRequest = new XMLHttpRequest();
getRequest.open('GET', baseUrl + encodeURIComponent(docName),
true);
getRequest.send();
getRequest.onreadystatechange = function(response) {
if (getRequest.readyState == 4 && getRequest.status == 200) {
var doc = JSON.parse(getRequest.responseText);
putRequest.open('PUT', baseUrl +
encodeURIComponent(docName) + '/' +
name + '?rev=' + doc._rev, true);
putRequest.setRequestHeader('Content-Type', type);
fileReader.readAsArrayBuffer(file);
fileReader.onload = function (readerEvent) {
putRequest.send(readerEvent.target.result);
};
putRequest.onreadystatechange = function(response) {
if (putRequest.readyState == 4) {
console.log(putRequest);
}
};
}
};
};
};
app();
};
Basically, I intercept the submit event of the form by binding my own function to the form's onsubmit event and returning false.
In that event handler I call my main function with two parameters. The first one being the document name and the second one being the file to upload.
In my uploadFile() function I set the file name, file type and grab some instances. The first HTTP request is a GET request to obtain the current revision of the document. If that request succeeds I prepare the PUT request (the actual upload request) by setting the previously obtained revision, the proper content type and then I convert the file to an ArrayBuffer. Once that's done I just send the HTTP request I've just prepared and then I relax.
The standalone attachment upload scheme looks like this:
PUT host/database/document/filename?revision=latest-revision
Of course using the proper content type in the HTTP request header.
Note: I'm well aware that I'm not making use of defensive programming here at all, I did that deliberately for brevity.

Resources