how to access a file from target URL after an XMLHttpRequest post - asp.net

I am trying to upload and save an image file to a server using an XMLHttpRequest POST after allowing file selection to be done on the client's side using HTML5 and java script (using an html input element).
My problem is that cannot find out how to actually get a hold of the file from the server side and save it to the server.
This is my code:
xhr = new XMLHttpRequest();
// Update progress bar etc
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
progressBar.style.width = (evt.loaded / evt.total) * 100 + "%";
}
else {
// No data to calculate on
}
}, false);
// File uploaded
xhr.addEventListener("load", function() {
progressBarContainer.className += " uploaded";
progressBar.innerHTML = "Uploaded!";
}, false);
xhr.open("post", "imageSave.aspx", true);
// Set appropriate headers
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.setRequestHeader("X-File-Name", file.fileName);
xhr.setRequestHeader("X-File-Size", file.fileSize);
xhr.setRequestHeader("X-File-Type", file.type);
// Send the file
xhr.send(file);

You can retrieve the file using Request.InputStream but that won't work unless there is no other data in your XHR entry.

Related

export excel from extjs grid

I want to export extjs grid content to excel file. So what i have done already:
i send to the servlet json content of the grid through Ext.Ajax.request, like
Ext.Ajax.request({
url : 'ExportToExcel',
method:'POST',
jsonData: this.store.proxy.reader.rawData,
scope : this,
success : function(response,options) {
this.onExportSuccess(response, options);
},
//method to call when the request is a failure
failure: function(response, options){
alert("FAILURE: " + response.statusText);
}
});
Then in servlet i get json in servlet do some stuff, e.g. create excel file, convert it to bytes array and try to put into response.
In Ext.Ajax.request in success method when i try to do something like this:
var blob = new Blob([response.responseText], { type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet});
var downloadUrl = window.URL.createObjectURL(blob);
var a = document.createElement("a");
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
it downloads excel file, but when i open it error occurs, saying format or extension is invalid.
WHY??
Whether it may depend on the encoding?
What i'm doing wrong?
Ext comes with an excel exporter built in. You may want to try using that to see if you get the desired results
grid.saveDocumentAs({
type: 'excel',
title: 'My Excel Title',
fileName: 'MyExcelFileName.xml'
});
From the toolkit : Ext.grid.plugin.Exporter

Meteor File Upload Not Working

I've added the packages cfs:standard-packages and cfs:filesystem to my meteor project.
I want to upload featured images for my blog using a form with this input.
<div class="form-group">
<label for="featuredImage">Featured Image</label>
<input type="file" id="fImage" required>
<p class="help-block">Please choose an image file.</p>
</div>
And the event javascript
Template.AddPost.events({
'change #fImage': function(event, template) {
var image = template.find('[id=fImage]').value;
var lastIndex = image.lastIndexOf("\\");
if (lastIndex >= 0) {
image = image.substring(lastIndex + 1);
}
if (!image.match(/\.(jpg|jpeg|png|gif)$/)) {
alert("not an image");
} else {
FS.Utility.eachFile(event, function(file) {
var fileObj = new FS.File(file);
Meteor.call('uploadFeaturedImage', fileObj);
});
}
}
});
The 'uploadFeaturedImage' method on the server is
Meteor.methods({
'uploadFeaturedImage': function(fileObj){
Uploads.insert(fileObj, function(err){
console.log(err);
});
}
});
When i choose an image file to upload i get this error -
"Exception while invoking method 'uploadFeaturedImage' Error: DataMan constructor received data that it doesn't support"
Anyone have any ideas why this is happening? Thank you.
I copied some explanation from the collectionFS documentation because it is really good described there.
When you need to insert a file that's located on a client, always call myFSCollection.insert on the client. While you could define your own method, pass it the fsFile, and call myFSCollection.insert on the server, the difficulty is with getting the data from the client to the server. When you pass the fsFile to your method, only the file info is sent and not the data. By contrast, when you do the insert directly on the client, it automatically chunks the file's data after insert, and then queues it to be sent chunk by chunk to the server. And then there is the matter of recombining all those chunks on the server and stuffing the data back into the fsFile. So doing client-side inserts actually saves you all of this complex work, and that's why we recommend it.
Have a look at HERE
So your method is not working because no data is sent to the server.

Alfresco - submitting dynamic forms to upload.post with javascript

I'm encountering issues with a dashlet that I'm trying to develop for Alfresco. It's a simple drag and drop file upload dashlet using HTML 5's drag and drop and file APIs. For the drop event listener, I call the following function which is seemingly the cause of all the problems:
function handleFileSelect(evt) {
var files = evt.target.files || evt.dataTransfer.files,
tmpForm, tmpDest, tmpMeta, tmpType, tmpName, tmpData;
dropZone.className = "can-drop";
evt.stopPropagation();
evt.preventDefault();
for (var i=0,f;f=files[i];i++) {
tmpForm = document.createElement('form');
tmpDest = document.createElement('input');
tmpDest.setAttribute('type', 'text');
tmpDest.setAttribute('name', 'destination');
tmpDest.setAttribute('value', destination);
tmpForm.appendChild(tmpDest);
tmpMeta = document.createElement('input');
tmpMeta.setAttribute('type', 'text');
tmpMeta.setAttribute('name', 'mandatoryMetadata');
tmpMeta.setAttribute('value', window.metadataButton.value);
tmpForm.appendChild(tmpMeta);
tmpType = document.createElement('input');
tmpType.setAttribute('type', 'text');
tmpType.setAttribute('name', 'contenttype');
tmpType.setAttribute('value', "my:document");
tmpForm.appendChild(tmpType);
tmpName = document.createElement('input');
tmpName.setAttribute('type', 'text');
tmpName.setAttribute('name', 'filename');
tmpName.setAttribute('value', f.name);
tmpForm.appendChild(tmpName);
tmpData = document.createElement('input');
tmpData.setAttribute('type', 'file');
tmpData.setAttribute('name', 'filedata');
tmpData.setAttribute('value', f);
tmpForm.appendChild(tmpData);
Alfresco.util.Ajax.request({
url: Alfresco.constants.PROXY_URI_RELATIVE + "api/upload",
method: 'POST',
dataForm: tmpForm,
successCallback: {
fn: function(response) {
console.log("SUCCESS!!");
console.dir(response);
},
scope: this
},
failureCallback: {
fn: function(response) {
console.log("FAILED!!");
console.dir(response);
},
scope: this
}
});
}
}
The server responds with a 500, and if I turn on debug level logging for web scripts, upload.post returns with:
DEBUG [repo.jscript.ScriptLogger] ReferenceError: "formdata" is not defined.
Which, to me at least, indicates that the form above isn't getting submitted properly (if at all). When digging through it all with Chrome dev tools, I notice that that request payload looks drastically different from something such as a REST client. The above code results in the request using Content-Type: application/x-www-form-urlencoded whereas using a REST client, or Alfresco Share's standard uploader(s) are using Content-Type: multipart/form-data. If I need to submit the form using multipart/form-data, what is the easiest way to write out the request body (with the boundaries, Content-Disposition's, etc...) to include the file being uploaded?
I ditched the idea of creating a form HTML Element through javascript, and assume that if a browser supports the File API, and the Drag and Drop API, that they will likely also support the XMLHttpRequest2 API. As per HTML5 File Upload to Java Servlet, The above code now reads:
function handleFileSelect(evt) {
var files = evt.target.files || evt.dataTransfer.files,
xhr = new XMLHttpRequest();
dropZone.className = "can-drop";
evt.stopPropagation();
evt.preventDefault();
for (var i=0,f;f=files[i];i++) {
formData = new FormData();
formData.append('destination', destination);
formData.append('mandatoryMetadata', window.metadataButton.value);
formData.append('contenttype', "my:document");
formData.append('filename', f.name);
formData.append('filedata', f);
formData.append('overwrite', false);
xhr.open("POST", Alfresco.constants.PROXY_URI_RELATIVE + "api/upload");
xhr.send(formData);
}
}
with the necessary event listeners to be added later. It would seem that the Alfresco AJAX methods that come stock and standard heavily modify the underlying requests being made, making it very difficult for one to simply send a FormData() object.

How to use the filename in the header as default filename for FileReference.download?

in our AIR application, I want to user to be able to download a file to a location of his choice. This can be easily done with:
var fileReference:FileReference = new FileReference();
fileReference.download( request );
The URLRequest points to a servlet http://myserver/myapp/download. If I do a navigateToUrl in our web application, the browser will properly use the filename put in the HTTP header by the server. However, in the AIR application, it will propose download as the file name for the user (because this is the last part of the URL probably).
How can I make sure the download in the AIR application will also use that name?
I am aware that the download method has an optional 2nd parameter to set the default file name, but I don't know what is in the HTTP header as file name at compile time of the client.
I managed to do it with the following code:
var stream:URLStream = new URLStream();
stream.addEventListener( HTTPStatusEvent.HTTP_RESPONSE_STATUS, function ( event:HTTPStatusEvent ):void
{
var fileName:String;
for each(var requestHeader:URLRequestHeader in event.responseHeaders)
{
if (requestHeader.name == "Content-Disposition")
{
fileName = requestHeader.value.substring( requestHeader.value.indexOf( "=" ) + 2, requestHeader.value.length - 1 );
logger.info( "Found filename in HTTP headers: {0}", [fileName] );
break;
}
}
stream.close();
logger.info("Start file download...");
var fileReference:FileReference = new FileReference();
fileReference.addEventListener(Event.COMPLETE, download_completeHandler );
fileReference.addEventListener(ProgressEvent.PROGRESS, download_progressHandler );
fileReference.download( request, fileName );
} );
stream.load( request );
I first use the URLStream class to get the HTTP headers. As soon as I have the headers, I close the stream (since it is a big file, I don't want to download the actual data just yet). From the headers, I extract the filename that is in the Content-Disposition part and use that name as the default name to pass into FileReference.download() method.

In Node.JS, when I do a POST request, what is the maximum size? [duplicate]

I created an upload script in node.js using express/formidable. It basically works, but I am wondering where and when to check the uploaded file e. g. for the maximum file size or if the file´s mimetype is actually allowed.
My program looks like this:
app.post('/', function(req, res, next) {
req.form.on('progress', function(bytesReceived, bytesExpected) {
// ... do stuff
});
req.form.complete(function(err, fields, files) {
console.log('\nuploaded %s to %s', files.image.filename, files.image.path);
// ... do stuff
});
});
It seems to me that the only viable place for checking the mimetype/file size is the complete event where I can reliably use the filesystem functions to get the size of the uploaded file in /tmp/ – but that seems like a not so good idea because:
the possibly malicious/too large file is already uploaded on my server
the user experience is poor – you watch the upload progress just to be told that it didnt work afterwards
Whats the best practice for implementing this? I found quite a few examples for file uploads in node.js but none seemed to do the security checks I would need.
With help from some guys at the node IRC and the node mailing list, here is what I do:
I am using formidable to handle the file upload. Using the progress event I can check the maximum filesize like this:
form.on('progress', function(bytesReceived, bytesExpected) {
if (bytesReceived > MAX_UPLOAD_SIZE) {
console.log('### ERROR: FILE TOO LARGE');
}
});
Reliably checking the mimetype is much more difficult. The basic Idea is to use the progress event, then if enough of the file is uploaded use a file --mime-type call and check the output of that external command. Simplified it looks like this:
// contains the path of the uploaded file,
// is grabbed in the fileBegin event below
var tmpPath;
form.on('progress', function validateMimetype(bytesReceived, bytesExpected) {
var percent = (bytesReceived / bytesExpected * 100) | 0;
// pretty basic check if enough bytes of the file are written to disk,
// might be too naive if the file is small!
if (tmpPath && percent > 25) {
var child = exec('file --mime-type ' + tmpPath, function (err, stdout, stderr) {
var mimetype = stdout.substring(stdout.lastIndexOf(':') + 2, stdout.lastIndexOf('\n'));
console.log('### file CALL OUTPUT', err, stdout, stderr);
if (err || stderr) {
console.log('### ERROR: MIMETYPE COULD NOT BE DETECTED');
} else if (!ALLOWED_MIME_TYPES[mimetype]) {
console.log('### ERROR: INVALID MIMETYPE', mimetype);
} else {
console.log('### MIMETYPE VALIDATION COMPLETE');
}
});
form.removeListener('progress', validateMimetype);
}
});
form.on('fileBegin', function grabTmpPath(_, fileInfo) {
if (fileInfo.path) {
tmpPath = fileInfo.path;
form.removeListener('fileBegin', grabTmpPath);
}
});
The new version of Connect (2.x.) has this already baked into the bodyParser using the limit middleware: https://github.com/senchalabs/connect/blob/master/lib/middleware/multipart.js#L44-61
I think it's much better this way as you just kill the request when it exceeds the maximum limit instead of just stopping the formidable parser (and letting the request "go on").
More about the limit middleware: http://www.senchalabs.org/connect/limit.html

Resources