using my chrome extension i would like to grab a file(and maybe change it) before it gets uploaded to a website. Particularly from file-inputs.
Put another way if i select a file with an input[type=file] i want my chrome extension to interrupt any submit and take the file. Then my extension applies its magic to the file and after that the file may be submitted/uploaded.
How can i approach this?
On problem occurs with the file path. If i grab the vaule of a file-input it always changes the actual path to " C:\fakepath\" due to HTML5 standard and compatibility issues.
How can i access the file then? Maybe it is saved temporarily in some chrome storage?
EDIT:
Well, i managed to read the file selected in the file input like this:
var file;
$('input[type=file]').change(function(e){
file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (event) {
console.log(event.target.result); //contains the file data
//maybe change data and use filewriter
};
reader.readAsDataURL(file);
};
Now i would like to use a FileWriter to write to e.target.files[0]
I followed this tutorial:
http://www.html5rocks.com/en/tutorials/file/filesystem/
but i am not able to create a proper FileWriter.
It is not necessary to write to the original file on the disk - might not even possible - but i need to change the data that is used to upload in the corresponding file-input form field.
There's no defined API for a Chrome extension to intercept the payload of a request (work in progress).
That being said, you can use a Content script to add an event listener which:
- Cancels the normal form submission.
- Reads the file as an
ArrayBuffer
using the FileReader
API.
- Modify the resulting
ArrayBuffer
after wrapping it in a view.
- Create a
Blob
from the modified data.
Reconstruct the form by creating a FormData
instance, then use the .append(name, value[, filename])
method.
Note: In the example below, I did not include the form reconstruction method. I only included the file upload part. There are two approaches to reconstruct the form:
- Write a method which is specific to your form.
- Write a general form-parsing method, which takes care of nameless/disabled/unchecked/... elements. If you want to take this route, have a look at the W3 specification for the Form submission algorithm.
- Submit the data using
XMLHttpRequest
. Note: If you're running this code in the context of your Chrome extension, don't forget to explicitly whitelist the URL at the permissions
section in the manifest file.
Here's an example of the implementation:
// Reference to the form:
var form = document.forms["uploadForm"];
form.addEventListener('submit', function(ev) {
ev.preventDefault(); // Cancel submission
var fileInput = form.querySelector('input[type="file"]');
var file = fileInput.files[0];
if (!file) return; // No file selected
var fileReader = new FileReader();
fileReader.onload = function() {
var arraybuffer = fileReader.result;
// To manipulate an arraybuffer, wrap it in a view:
var view = new Uint8Array(arraybuffer);
view[0] = 0; // For example, change the first byte to a NULL-byte
// Create an object which is suitable for use with FormData
var blob = new Blob([view], {type: file.type});
// Now, the form reconstruction + upload part:
var formData = new FormData();
formData.append(fileInput.name, blob, file.name);
// ... handle remainder of the form ...
// Now, submit the form
var xhr = new XMLHttpRequest();
xhr.open('POST', form.action);
xhr.onload = function() {
// Do something. For example:
alert(xhr.responseText);
};
xhr.onerror = function() {
console.log(xhr); // Aw. Error. Log xhr object for debugging
}
xhr.send(formData);
};
fileReader.readAsArrayBuffer(file);
});