I have an ExtJs form with an upload field. When I sumbit the form, the Accept-header is wrong. The response is JSON yet the sent Accept-header is:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
My educated guess is that it's the browsers default value.
In Chrome this results in a warning: Resource interpreted as Document but transferred with MIME type application/json.
In FireFox this results in a file download.
Conclusion: I have to change/set the Accept-header to application/json
Sencha's documentation sais it has a headers parameter, but I've tested and for fileupload it does not work. A comment said it's not supported. (found same result in another thread)
Any suggestions to get rid of the file download/ set the right Accept-header... It doesn't have to be a ExtJs sollution. If you can give me a plain javaScript solution for setting the accept header on a file upload form, I can probably mold it into the sencha framework.
UPDATE:
The ExtJS form submit:
form.submit({
url: API_URLS.addDocument,
waitMsg: 'Uploading your document...',
headers: {
"Accept": 'application/json' //doesn't work
},
success: function() {
...
},
failure: function(){
...
}
});
Behind the scenes it creates an ordinary form similar to this:
<form action="API_URLS.addDocument" enctype="multipart/form-data" method="post">
<input type="file"/>
</form>
which can be submitted through javaScript (submit())
The Accept header is just asking the server to respond with data of a given type. The * in the default header means "or anything else" (although the q value puts a lower priority then that).
If the response is JSON and you want JSON, then you don't need to touch the Accept header at all.
The problem is that, if I'm reading between the lines correctly, you are trying to perform an Ajax file upload using an iframe, and Firefox doesn't try to render JSON files as documents.
There are two ways around this.
Present the response as HTML instead of JSON and then extract the data from it using DOM
Use XMLHttpRequest 2 and the File API to upload the files instead of an iframe. (Note: This uses new APIs that have limited browser support).
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am writing a webapp that lets the user upload photos, and then returns data about those photos to the front end to trigger some activity.
I started this off using a tutorial/guide I found online, here
I was however very surprised to find that this worked without javascript. I do not understand how pressing the button sends a request for there to be a pop-up window asking to select a file. How does it know that the button is for file uploading? No where in the HTML do I give it an obvious attribute that tells it to upload a file, and nowhere in python/Flask do I select the button used for uploading.
I also noticed, to my surprise, that in the example given, the route MUST be called "/upload" to work. Again, I can not see where any of this is defined or where I could change it. The only files used for the demo on that link (which is the basis of my webapp) are app.py and index.html (the setup.py file does not seem to be needed to run the webserver)
As my webapp has progressed, I tried to add a javascript file that would take a response from the /uploads route and display it on the front end, but soon ran into trouble. It seems I can only run /uploads from whatever mysterious force is currently running it. My javascript can't access it, and so I have no way of getting the response into JS so that I can display it on the front end in the way I want.
Can someone help me understand how the file upload server in the link works, so that I can modify it to work with my JavaScript?
Please note that my webapp is basically just the program in that link with a bunch of analysis done on the files that are uploaded. The only change I made in terms of how the webapp works is that instead of redirecting you to the uploaded file, it should return a string with information on that file.
I don't feel it is worth posting too much of my python and HTML code, since all the important stuff is in that link, but the javascript file is below.
"use strict";
var main = function() {
console.log("i am functioning!")
var show_similar_img = function(){
//Read megastatus
$.ajax({
method: "GET",
url: "/upload",
// contentType: 'application/json',
dataType: "string"
})
.done(function(media_info){
console.log(media_info)
});
}
$("#upload-btn").on("click",function(){
console.log("button pressed!")
show_similar_img()
})
}
console.log("i am being run!")
$(document).ready(main);
The <input> element's type attribute is file, which is how the browser knows how to handle it in the particular way that it does--as you noticed, by opening a pop-up modal window which prompts the user to select a file.
The route has to be called upload because the <form> element's action attribute value is also called upload. You could change the name of the route if you also changed the action of the form.
You can in fact access file information (for a file associated with the input element) using JavaScript thanks to the File API. Mozilla Developer Network has an excellent guide for it: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications
With regards to your actual implementation: first, you'll also want to prevent your form submission from being handled in the 'regular' (synchronous) way, so you'll need to call preventDefault on the event:
$("#upload-btn").on("click",function(event) {
event.preventDefault();
console.log("button pressed!")
show_similar_img()
})
Second, I am assuming that you want to actually send the file to the server (run on Python/Flask), so you want your AJAX request to be a POST rather than a GET. Therefore you'll need to modify your show_similar_img, to send the request as a POST and also to include the file in the data of the request, using the aforementioned File API. Something like this:
var show_similar_img = function(){
var formData = new FormData();
var file = $("input[type='file']")[0].files[0];
formData.append("file", file);
$.ajax({
url : "/upload",
type : "POST",
data : formData,
contentType: false,
processData: false
})
.done(function(media_info){
console.log(media_info)
});
}
Edit--I should add that I'm not really familiar with Flask or the intricacies of its request object. I assume that regardless of whether the file is uploaded as part of a form submission or asynchronous request that it would still be accessible at request.files['file'], but it is possible that Flask doesn't make asynchronously uploaded files available in the request.files dictionary. I am very sure, though, that the file would be accessible somewhere on the request object, so you may need to refer to the Flask documentation. You could also use pdb to add a breakpoint in your server-side code and inspect the request object to see what it holds (and where it holds it).
I have a .csv file that I wish to load that contains information that the .HTML page will format itself with. I'm not sure how to do this however,
Here's a simple image of the files: http://i.imgur.com/GHfrgff.png
I have looked into HTML5's FileReader and it seems like it will get the job done but it seems to require usage of input forms. I just want to load the file and be able to access the text inside and manipulate it as I see fit.
This post mentions AJAX, however the thing is that this webpage will only ever be deployed locally, so it's a bit iffy.
How is this usually done?
Since your web page and data file are in the same directory you can use AJAX to read the data file. However I note from the icons in your image that you are using Chrome. By default Chrome prevents just that feature and reports an access violation. To allow the data file to be read you must have invoked Chrome with a command line option --allow-file-access-from-files.
An alternative, which may work for you, is to use drag the file and drop into onto your web page. Refer to your preferred DOM reference for "drag and drop files".
You can totally make an ajax request to a local file, and get its content back.
If you are using jQuery, take a look at the $.get() function that will return the content of your file in a variable. You just to pass the path of your file in parameter, as you would do for querying a "normal" URL.
You cannot make cross domain ajax requests for security purposes. That's the whole point of having apis. However you can make an api out of the $.get request URL.
The solution is to use YQL (Yahoo Query Language) which is a pretty nifty tool for making api calls out of virtually any website. So then you can easily read the contents of the file and use it.
You might want to look at the official documentation and the YQL Console
I also wrote a blog post specifially for using YQL for cross domain ajax requests. Hope it helps
You can try AJAX (if you do not need asynchronous processing set "async" to false. This version below ran in any browser I tried when employed via a local web server (the address contains "localhost") and the text file was indeed in the UTF-8-format. If you want to start the page via the file system (the address starts with "file"), then Chrome (and likely Safari, too, but not Firefox) generates the "Origin null is not allowed by Access-Control-Allow-Origin."-error mentioned above. See the discussion here.
$.ajax({
async: false,
type: "GET",
url: "./testcsv.csv",
dataType: "text",
contentType: "application/x-www-form-urlencoded;charset=UTF-8",
success: function (data) {
//parse the file content here
}
});
The idea to use script-files which contain the settings as variables mentioned by Phrogz might be a viable option in your scenario, though. I was using files in the "Ini"-format to be changed by users.
I'm having intermittent problems, trying to to upload files, using ajaxfileupload.js. Most times, the request has teh correct payload, as in A). But sometimes, the request gets sent off without the filename (and contents) as seen in this pastebin (B).
It seems to be similar to this problem. This post also talks about the problem. But I'm pretty sure I have the correctr element ID.
And this post suggests using the jquery.form plugin (here and here). But before I change components (having to re-engineer), I want to be sure there isn't an easy way to fix my current problem.
A)
…
Request Payload
------WebKitFormBoundaryXOoAbr8cm53B1pGS
Content-Disposition: form-data; name="convert"; filename="some-file.jpg"
Content-Type: application/octet-stream
…
B)
http://pastebin.com/ubEbb9dV
Has someone had this problem before? Is there a way to avoid it?
Thanks
----> EDIT
So this is how I'm calling the function. i) The inputId passed in definitely exists. And ii) the file selected definitely exists on the file system. And this works most of the time. But now that I think about it, I'm using this plugin in conjunction with the "jquery.jeditable.js" plugin. Could that or any other plugin be turfing some functions in "ajaxfileupload"?
$.ajaxFileUpload (
{
url: '/api/upload/image',
secureuri: false,
fileElementId: inputId,
success: successFn,
error: errorFn
}
);
By default jQuery use GET as request Method. In the case of the question you reference here, Steven is not setting correctly the method property of for the ajax request. What I want to see i how you are sending the form (Your javascript/Jquery code).
Can I send a file as multipart by XMLHttpRequest to a servlet?
I am making a form and submitting it as multipart, but somehow I am not getting a response for successfully uploading it. I do not want the page to be refreshed, so it has to take place by Ajax.
That's only possible with the XHR FormData API (previously known being part of as "XHR2" or "XHR Level 2", currently known as "XHR Advanced Features").
Given this HTML,
<input type="file" id="myFileField" name="myFile" />
you can upload it as below:
var formData = new FormData();
formData.append("myFile", document.getElementById("myFileField").files[0]);
var xhr = new XMLHttpRequest();
xhr.open("POST", "myServletUrl");
xhr.send(formData);
XHR will take care about proper headers and request body encoding and the file will in this example be available on the server side as form-data part with the name myFile.
You need to keep in mind that FormData API is not supported in older browsers. At caniuse.com you can see that it's currently implemented in Chrome 7+, Firefox 3.5+, Safari 5+, Internet Explorer 10+ and Opera 12+.
In case you're using jQuery, then you might be tempted to use its $.val() function as below:
formData.append("myFile", $("#myFileField").val());
But this is incorrect as it doesn't return the whole File object, but merely the file name as String which is utterly useless as it doesn't contain the file contents.
If you don't want to use document.getElementById() for some reason, then use one of the following instead:
formData.append("myFile", $("#myFileField").prop("files")[0]);
formData.append("myFile", $("#myFileField")[0].files[0]);
An alternative is to use the jQuery Form plugin. Your entire form, when written and functioning properly without any line of JavaScript code, will then instantly be ajaxified with just the following line:
$("#formId").ajaxForm(function(response) {
// Handle Ajax response here.
});
It also supports file uploads as well by a hidden iframe trick. See also this jQuery Form documentation for an in-depth explanation. You may only need to change the servlet code to be able to intercept on both normal (synchronous) and Ajax (asynchronous) requests. See also this answer for a concrete example: Simple calculator with JSP/Servlet and Ajax
Either way, the uploaded file should then be available in the doPost() method of a #MultipartConfig servlet as follows:
Part myFile = request.getPart("myFile");
Or if you're still on Servlet 2.5 or older, use Apache Commons FileUpload the usual way. See also this answer for a concrete example: How can I upload files to a server using JSP/Servlet?
It's not possible to send multipart/form-data with XMLHttpRequest (though it is possible in modern browsers, with XHR2. See BalusC's answer).
A common way to achieve what you want is to use a regular form, but in an iframe instead. This way, only the iframe is refreshed on upload.
I would like to upload a file using JQuery-File-Upload, but using HTTP "PUT" instead of multipart-forms. According to their site:
- Multipart and file contents stream uploads:
Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload).
but I cannot find anywhere in their documentation as to how to do this. Can anyone help?
According to : https://github.com/blueimp/jQuery-File-Upload/wiki/Options
method
The method of the HTTP request used to
send the file(s) to the server. Can be
POST (multipart/formdata file upload)
or PUT (streaming file upload).
Accepts a String or a function
returning a String.
You should use :
$('#file_upload').fileUpload({
namespace: 'file_upload_1',
url: '/path/to/upload/handler.json',
method: 'PUT'
});
I love REST too but you might want to make sure you unit test well on the browsers you need to support.
http://api.jquery.com/jQuery.ajax/
The type of request to make ("POST" or "GET"), default is "GET". Note: Other HTTP request methods, such as PUT and DELETE, can also be used here, but they may not supported by older browsers.
See this answer
How do I PUT data to Rails using JQuery