When a user on our website wants to create a new Object, they are required to upload an XML file, which is then passed to a controller action using AJAX. The controller method parses attributes from the XML file and passes them back to the JavaScript, which then auto-populates most of the new Object form fields.
The HTML looks like this:
<input type="file" name="upload_datafile" id="upload_datafile" accept=".xml">
The file is pulled from the file input using the following:
$("#upload_datafile").change(function() {
var file = $("#upload_datafile").prop("files")[0];
...
The Capybara test looks like this:
scenario 'upload file', js: true do
expect(page).to have_css '#upload_datafile'
attach_file('upload_datafile', File.expand_path('spec/fixtures/files/valid.xml'))
expect(page).to have_field 'name', with: 'Valid Object'
end
The 'name' field should be populated when 'valid.xml' is uploaded and has been parsed. Instead, our XML parser, which tries to read the file, throws the following error:
NoMethodError:
undefined method 'read' for "undefined":String
I have tested this extensively manually and no error is thrown. The file path is also correct in the Capybara test. If I throw a breakpoint into the Capybara test I can manually upload a file in the browser and it will work just fine. It appears that Capybara is not uploading the file and and instead our JavaScript passes the string 'undefined' to the controller action because that's the result when trying to get the 0th file in the 'files' prop of the file input during the Capybara test.
Why isn't Capybara actually uploading the file and/or why isn't the file accessible through JavaScript?
Related
I am trying to select a local json file and load it in my blazor client component.
<input type="file" onchange="LoadFile" accept="application/json;.json" class="btn btn-primary" />
protected async Task LoadFile(UIChangeEventArgs args)
{
string data = args.Value as string;
}
P,S I do not understand , do i need to keep track both the name of the file and the content when retrieving it ?
I guess you're trying to read the contents of a JSON file on the client (Blazor), right? Why not on the server !?
Anyhow, args.Value can only furnish you with the name of the file. In order to read the contents of the file, you can use the FileReader API (See here: https://developer.mozilla.org/en-US/docs/Web/API/FileReader). That means that you should use JSIntrop to communicate with the FileReader API. But before you start, I'd suggest you try to find out if this API have been implemented by the community (something like the localStorage, etc.). You may also need to deserialize the read contents into something meaningful such as a C# object.
Hope this helps...
There is a tool that can help, but it currently doesn't support the 3.0 preview. https://github.com/jburman/W8lessLabs.Blazor.LocalFiles
(no affiliation with the developer)
The input control will give you the location of the file as a full path along with the name of the file. Then you still have to retrieve the file and download it to the server.
Late response but with 3.1 there is an additional AspNetCore.Components module you can download via NuGet to get access to HttpClient extensions. These make it simple:
// fetch mock data for now
var results = await _http.GetJsonAsync<WellDetail[]>("sample-data/well.json");
You could inject the location of the file from your input control in place of the "sample-data/well.json" string.
Something like:
using Microsoft.AspNetCore.Components;
private async Task<List<MyData>> LoadFile(string filePath)
{
HttpClient _http;
// fetch data
// convert file data to MyData object
var results = await _http.GetJsonAsync<MyData[]>(filePath);
return results.ToList();
}
I've a Spring MVC application that is wrapped with Swagger annotations.
<spring.version>4.1.8.RELEASE</spring.version>
<java-version>1.7</java-version>
<springfox-version>2.1.2</springfox-version>
I've a controller with two resource endpoints to allow file upload - one endpoint for a single file upload and other with multiple file upload.
Single file upload -->
public #ResponseBody UploadAPIResponse postInboundFile(
#ApiParam(value = "file to upload") #RequestParam("file") MultipartFile file,
#ApiParam(value = "Inbound trigger flag ") #RequestParam("triggerInbound") Boolean triggerInbound)
throws SQLException, Exception {
Multi file upload -->
public #ResponseBody BulkUploadAPIResponse postInboundFilesAsync(
#ApiParam(value = "files to upload") #RequestParam("files") MultipartFile[] files,
#ApiParam(value = "Inbound trigger flag ") #RequestParam("triggerInbound") Boolean triggerInbound,
HttpServletRequest request) throws SQLException, Exception {
On viewing the Swagger UI for the api documentation,
I see that for single file upload API, against the "file" parameter, I get a file upload button.
However for the multi file upload API, I get the "files" parameter as a text box.
Can someone pls help me how can I get a file upload button against the "files" parameter of multi-files upload API and I'm able to upload multiple files as part of single request ?
I've gone through various other posts on this context but not able to find a concrete approach to address this issue.
PS : I've the understanding that naming the parameter as "file" provides the file upload button automatically through Swagger-UI. I tried to use the parameter name as "file" instead of "files" for the multi-file upload API but that didn't help; i still end up getting a text box (probably reason being that argument is an array of MultipartFile).
Thanks in advance for any pointers/suggestions.
I'm using version 12.01 of the excellent ng-file-upload and attempting to create an e2e test with protractor using Chrome 49. I'm using sendKeys to path the file path, and I'm able to see the upload being triggered, but the file size in the
<button
class="avatar-upload__button"
ngf-select="uploadFiles($file, $invalidFiles)"
ng-model='ngfFile'
accept="image/*"
ngf-max-size="14.5MB">
</button>
I'm able to see the file upload being called in this function:
$scope.uploadFiles = (file, errFiles) => {
}
But at this point file.size is 0, where when I run this manually, i get the correct size. I wouldn't be too fussed about this except that the upload seems to be getting choked off/is not happening (presumably because the file information is bad).
My guess at this point is it is related to using this on a button rather than an input[type="file"]. I'm going to start digging into ng-file-upload, but any suggestions/ideas appreciated.
I knew something smelled bad here because nobody else was having this problem. I assembled the path incorrectly and the file did not exist.
I am trying to build a simple photo upload app on Ionic (Cordova). I am using the cordovaImagePicker plugin to have the user select images from the mobile device. This plugin returns an array of paths on the device.
For handling the upload part I am using jquery-file-upload (mostly because that is what I used for the browser version and I am doing all kinds of processing for which I have the code ready). The problem is however that jquery-file-upload expects to work with an input element <input type="file"> which creates a javascript File object containing all kinds of metadata.
So in order to get the cordovaImagePicker to work with jquery-file-upload, I figure I have to convert the filepath to a File object. Below I am using the cordova file plugin to achieve this:
$cordovaImagePicker.getPictures($scope.pickOptions).then(function(filelist) {
$.each(filelist, function (index, filepath) {
$window.resolveLocalFileSystemURL(filepath, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
fileObj = new File([this.result],"filename.jpg",{type: "image/jpeg"});
// send filelist from cordovaImagePicker to jquery-fileupload as if through file input
$('#fileupload').fileupload('send', {files: fileObj});
};
reader.readAsArrayBuffer(file);
}, function(e){$scope.errorHandler(e)});
}, function(e){$scope.errorHandler(e)});
});
}, function(error) {
// error getting photos
console.log('Error selecting images through $cordovaImagePicker');
});
So first of all this is not really working correctly, apparently I am doing doing something wrong, since for example the type attribute ends up being another object that contains the type attribute with the correct values (and other such weird issues). I would be happy if someone could point out what I am doing wrong.
Surely there must be something (cordova plugin?) that I am not aware of that does this conversion for me (including for example adding a thumbnail)? Alternatively, maybe there is something that can easily make jquery-file-upload work with filepaths? I couldn't find anything so far...
However, it feels I am trying too hard here to force connecting two components that were just not built to work together (File objects vs filepath) and I should maybe just rewrite the processing and use the cordova file transfer plugin?
I ended up rewriting the uploader with the cordova-file-transfer which works like a charm. I wasted more time trying to work around it than just rewriting it from scratch.
I download fine uploader 3.5, created http handler for a file upload function in my little website . the website is done by asp.net ajax and jquery. it runs at IE9. every time I upload a file, there is a list of file names shown below the load button. if I don't want thme, what should I do?
my code is like this:
html: ...
'<tr><td><div id="jquery-wrapped-fine-uploader"></div></td></tr>...
'ajax/jquery:...
'$('#jquery-wrapped-fine-uploader').fineUploader({
'request: { endpoint: 'xxx.ashx' }
'})
'$('#jquery-wrapped-fine-uploader').on("complete",
'function (event, id, fileName, responseJSON) {
' alert("UPLOAD SUCCESS");
' $.ajax({some ajax calls here});
' })
// WHERE TO PUT this TO CLEAR the UPLOADED FILE LIST??? $('#jquery-wrapped-fine-uploader').fineUploader('reset');
XXX.ashx:
'... public void ProcessRequest (HttpContext context) {
'do some http request work..
'context.Response.ContentType = "text/plain";
'context.Response.Write("{\"success\":true}");
'}
My question is:
I want to completely remove the uploaded file list which shows automatically in green color ( or red if they fail), in order to clear them, I tried to put: $('#jquery-wrapped-fine-uploader').fineUploader('reset'); right after .on('complete'), it's not working, also #jquery-wrapped-fine-uploader seems cached all the time. please help on this.
If you don't want to see the file list at all, you should be using FineUploaderBasic mode instead of using FineUploader mode and then removing all elements in the pre-built UI. FineUploaderBasic mode gives you access to the API, options, and callbacks, but assumes you will be creating your own UI. In other words, FineUploaderBasic mode does not create any DOM elements (except the opaque file input element as a child of your button container, if you supply one). This is all explained (in a great amount of detail) in the documentation.
Start here: http://docs.fineuploader.com