Grab file from chrome webRequest onBeforeRequest - google-chrome-extension

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"]);

Related

Mobile Safari video upload makes site refresh

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)
}

Why is my image file being converted to a string?

Edit, original question has been resolved as to why file was converted to string. The code has been edited to reflect these corrections. The API handler is now outputting object as data type and buffer as the value of request.payload.file.
I'm using Aurelia to make a Single Page App. There is a HTML form that accepts two input fields, one for a file, one for text. These fields are bound to variables (selecetdImage and title) in an associated TypeScript view model. In the viewmodel they are used as arguments in a function that appends them to formData and sends a http post request with the formData to an Node/js Hapi framework API handler.
When I console.log(typeof(selectedImage) in the Aurelia app, it states object, but when I console log typeOf(selecetdImage) in the handler, I get String. I'm guessing this is why my function isn't working and giving 500 error messages
The handler itself works. I used it in a MVC server based web app. In that context, HTML form triggers a post request, and the MVC handler successfully receives the file, writes it to local/temp.img and uploads it to cloudinary.
But with the API version, where I assembled the form data myself as above, the file isn't written to local/temp.img and the cloudinary upload fails.
Edit.
I changed the viewmodel variables to
title = null;
files = null;
and I changed the formData append function to:
formData.append('file', File, files[0]);
As per the example here. The code below is now modified to match this update.
Now when I console log the value of file in the API handler, the output is:
<Buffer ff d8 ff e0 00 10.......
I'm not sure what to do with this data. I assume it's the image binary data in octal? And if so, does anyone know how to write it as an image in node?
The payload is no longer of type string, now it's type object.
<form submit.delegate="uploadPhoto()" enctype="multipart/form-data">
<div class="two fields">
<div class="field">
<label>File</label>
<input type="file" name="file" accept="image/png, image/jpeg" files.bind="files">
</div>
<div class="field">
<label>Title</label> <input value.bind="title">
</div>
</div>
<button type="submit"> Upload </button>
</form>
//photoUpload.ts// (view model associated with above html
#inject(POIService)
export class PhotoForm {
#bindable
photos: Photo[];
title = null;
files = null;
constructor (private poi: POIService) {}
uploadPhoto() {
const result = this.poi.uploadPhoto(this.title, this.files);
console.log(this.title);
console.log(result);
}
//POIService (where contains injected function to create HTTP request
async uploadPhoto(title: string, files){
console.log("now uploading photo for: " + this.currentLocation)
let formData = new FormData();
formData.append("title", title);
formData.append("location", this.currentLocation); //don't worry about this variable, it's set by another function every time a page is viewed
formData.append("file", files[0]);
const response = await this.httpClient.post('/api/locations/' + this.currentLocation + '/photos', formData);
console.log(response);
}
//API Handler (accepts HTTP request, writes the image to a local folder, the uploads to cloudinary and returns the url and photo_id which are stored in a Mongod document
create: {
auth: false,
handler: async function(request, h) {
const photo = request.payload.file;
await writeFile('./public/temp.img', photo);
const result = await cloudinary.v2.uploader.upload('./public/temp.img', function(error, result) {
console.log(result)
});
const newPhoto = new Photo({
title: request.payload.title,
url: result.url,
public_id: result.public_id,
location: request.params.name
})
await newPhoto.save();
return newPhoto;
}
},
Is it a very long string, containing "data:b64" in the first 15 or so characters? If so, that means it's the base64 data.

Post multipart/form-data to endpoint

I'm trying to create an upload form for excel files with angular 6. I have implemented a file chooser with which i want to upload (post) excel files to a certain endpoint that expects "MULTIPART_FORM_DATA". Now i have read that you should not set the content type in the header for angular versions above 5 but if i do not include the content-type in the header the angular application automatically sets it to
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", which the server does not expect and hence results in a "bad request". So how can i implement a valid "post" for multipart/form-data with angular 6?
the endpoint looks something like this:
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadExcel(
#FormDataParam("file") InputStream inputStream,
#FormDataParam("file") FormDataContentDisposition contentDispositionHeader){...}
the angular component looks something like this:
handleFileInput(event: any): void {
if (!event.target.files.length) {
return;
}
this.fileToUpload = event.target.files.item(0);}
private uploadFile(): void {
this.fileService.uploadFile(this.fileToUpload).subscribe(
(res: any) => {
console.log('upload succeeded');
}
);}
the html form looks something like this:
<form (submit)="uploadFile()" enctype="multipart/form-data">
<label for="file">choose excel file to upload: </label>
<input type="file" name="file" id="file" accept=".xls,.xlsx" (change)="handleFileInput($event)">
<input type="submit" name="submit" class="submitButton">
and the service looks like this:
uploadFile(file: File): Observable<any> {
const fd: FormData = new FormData();
fd.append('file', file, file.name);
return this.http.post(this.fileURL, file);
}
I found the mistake I've made: I passed the wrong argument to the http.post call.
The service should of course look like this:
uploadFile(file: File): Observable<any> {
const fd: FormData = new FormData();
fd.append('file', file, file.name);
return this.http.post(this.fileURL, fd);
}

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

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