Upload file to CouchDB #88

Closed
paldepind opened this Issue Dec 29, 2013 · 15 comments

Projects

None yet

5 participants

@paldepind

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.

@danialfarid
Owner

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

@danialfarid
Owner

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.

@paldepind

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.

@paldepind

Sounds good with inbuilt support for the FileReader API 👍

@danialfarid
Owner

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.

@paldepind

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 :-)

@danialfarid
Owner

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);
        });
    }

@paldepind

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!

@paldepind paldepind closed this Jan 1, 2014
@killfill
killfill commented Apr 3, 2014

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!!

@danialfarid
Owner

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.

@killfill
killfill commented Apr 3, 2014

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

@munkh-altai

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'

});
}

@munkh-altai

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

@danialfarid
Owner

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

@rohand89
rohand89 commented Nov 4, 2015

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment