danialfarid / ng-file-upload

Lightweight Angular directive to upload files with optional FileAPI shim for cross browser support

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Upload file to CouchDB

paldepind opened this issue · comments

I'm trying to upload an image with the following code:

$scope.onFileSelect = function(ins, files) {
  _.each(files, function(file) {
    var fileReader = new FileReader();
    fileReader.onload = function(e) {
      $timeout(function() {
        file.previewUrl = e.target.result;
      });
    };
    fileReader.readAsDataURL(file);
    $upload.upload({
      url: projectRepository.attachmentUrl(ins, file.name),
      method: "PUT",
      file: file,
    }).progress(function (evt) {
      console.log(evt);
    }).success(function(data) {
      // ...
    }).error(function(data) {
      console.log(data);
    });
  });
};

I'm uploading the file to CouchDB (which I don't think matters since CouchDB doesn't do any processing on the file) and the uploaded file end up with the content type "application/json". I fixed that by setting the headers manually with

headers: { "Content-Type": file.type },

And outcommenting the line in the angular-file-upload source that sets the content type to undefined. This fixes the content type, and sets it correctly according to the filetype but the uploaded file still ends up on the server in some corrupted form that won't show correctly in the browser.

To upload to CouchDB you gotta send a request with the content type of the file and the file content so you don't need to use $upload.upload() which will send a multipart form data request. Just use regular angular $http({ method:'PUT', headers: { "Content-Type": file.type }, ... }

Here is an example of how to do it:
http://stackoverflow.com/questions/11864257/how-to-upload-a-file-attachment-from-the-browser

The FileReader api is gonna be supported in the next release of FileAPI around February 14. Once it is released I will integrate it with angular-file-upload so that FileReader will be supported cross browser with the FileAPI polyfill.

Ok. So the issue it that the backend needs to handle multipart fomr data requests and CouchDB doesn't?

If I use $http I loose the possibility of using the progress callback. I might do the upload with plain jQuery then.

Sounds good with inbuilt support for the FileReader API 👍

Oh I see, so you basically want to get the progress event from angular with this library. I can add another service method to just send a regular $http request with progress callback.

I let you know once it is done.

Yes! That sounds exactly like what I need. Then I'd be able to use the directives, and the other great features in a way compatible with CouchDB. Thanks a lot for your great support and for creating this library :-)

version 1.2.0 now supports this:

    var fileReader = new FileReader();
    fileReader.readAsArrayBuffer(file);
    fileReader.onload = function(e) {
        $upload.http({
            url: 'upload',
            headers: {'Content-Type': file.type},
            data: e.target.result
        }).then(function(response) {
            //success;
        }, null, function(evt) {
            $scope.progress[index] = parseInt(100.0 * evt.loaded / evt.total);
        });
    }

Super sweet! Thanks a lot for implementing this feature it works flawlessly!

I figured out that this syntax works as well which I prefer:

$upload.http({
    url: 'upload',
    headers: {'Content-Type': file.type},
    data: e.target.result
}).progress(function(ev) {
    //progress
}).success(function(data) {
    //success
}).error(function(data) {
    //error
});

Thanks again!

Hi!

I got a backend that does not support multipart either, so im using the .http() method.
When i try to upload big files (i.e. 500MB), the browser crashed. I can see FileRead is reading the whole file, when finished, triggers the onload event where $upload.http() is been called. Its crashing there.

@danialfarid is there a way to stream the file? $upload.upload() seem to do it...

Thanks!!

There are workarounds using file.slice() but it is not embedded in the plugin.
Could you create a separate issue, if I get time later on I will add it to the plugin.
For now you can use something like this to split the file in chunks and then call $upload.http() with the file being sliced data then on the server append the slices to the file.

Ok issue created!
Yeah, that would be an option, but it will require to modify the backend too.
Thanks!!

i have one question
I am beginner of Angularjs and my English not good sorry.
my question: form with 2 input type text, 2 input type file and 1 submit button.
when click submit button post to back-end input text and input file.
how to set up start() function.
i need your help

this is my false code
$scope.start = function(index) {
$scope.progress[index] = 0;
$scope.upload = $upload.upload({
url : 'image_upload_script.php',
method: 'POST',
data : {
myModel2 : $scope.myModel1,
myModel2 : $scope.myModel2,

            },
            file: $scope.file1,
            fileFormDataName: 'uploaded_file',
                            file: $scope.file2,
            fileFormDataName: 'uploaded_file2'

});
}

Hello how i change to Multiple File Input Fields in One Form

@altaihero Please create a separate New Issue. This issue is closed and your question is not related to this one.

I have a scenario in which i have the file upload control in a popup
If I select a.jpg for one item then when i try to add files for the second item and i select a.jog again it doesn't upload the file since this file was already posted to the server for the first item, is there any workaround for this if i can reinitialize the control or maybe some other workaround?