I am trying to do chunked file upload with angular-js and jquery-file-uplad (form github/blueimp). Backend is rails application running on nginx.
Jquery file upload is sending only first chunk and then stops on receiving 201 from nginx server.
Document here specifies that nginx should return 201 Created and not 200. Can't seem to figure out what is wrong here.
Following are relevant code sections
JS
(function () {
'use strict';
var url = 'jquploadhandle';
blueshiftApp.config([
'$httpProvider', 'fileUploadProvider',
function ($httpProvider, fileUploadProvider) {
delete $httpProvider.defaults.headers.common['X-Requested-With'];
fileUploadProvider.defaults.redirect = window.location.href.replace(
/\/[^\/]*$/,
'/cors/result.html?%s'
);
}
])
.controller('DemoFileUploadController', [
'$scope', '$http', '$filter', '$window',
function ($scope, $http) {
$scope.options = {
url: url,
dataTtype: 'text',
multipart: false,
maxChunkSize: 4000000, //Bytes
sequentialUploads: true,
};
$scope.loadingFiles = false;
$('#fileupload').bind('fileuploadadd', function(e, data){
if (data.headers === undefined) {
data.headers = {};
}
data.headers['Session-Id'] = "0000000277"
});
}
])
.controller('FileDestroyController', [
'$scope', '$http',
function ($scope, $http) {
var file = $scope.file,
state;
if (file.url) {
file.$state = function () {
return state;
};
file.$destroy = function () {
state = 'pending';
return $http({
url: file.deleteUrl,
method: file.deleteType
}).then(
function () {
state = 'resolved';
$scope.clear(file);
},
function () {
state = 'rejected';
}
);
};
} else if (!file.$cancel && !file._index) {
file.$cancel = function () {
$scope.clear(file);
};
}
}
]);
}());
HTML Markup
<form id="fileupload" method="POST" enctype="multipart/form-data" data-ng-controller="DemoFileUploadController" data-file-upload="options" data-ng-class="{'fileupload-processing': processing() || loadingFiles}">
<!-- Redirect browsers with JavaScript disabled to the origin page -->
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<!-- The fileinput-button span is used to style the file input field as button -->
<div class="form-group col-md-offset-4">
<label class="form-inline control-label col-md-3">
Upload File
<span class="required">* </span>
</label>
<input type="file" name="file" accept="text/csv, application/json" ng-required="true" ng-disabled="disabled">
<label> Download Sample
<a href='/crm_feeds.csv'> CSV <i class='fa fa-share-square-o'></i> </a>
</label>
<p ng-show="invalid_file" class="help-block">CRM data file is required.</p>
</div>
<div class="form-group">
<div class="form-inline col-md-5" >
<button type="button" class="btn btn-default cancel" data-ng-click="cancel()">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button type="button" class="form-inline btn btn-primary start" data-ng-click="submit()">
<i class="glyphicon glyphicon-upload"></i>
<span>Validate</span>
</button>
</div>
</div>
<div>
<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div>
<!-- The global progress state -->
<div class="col-lg-5 fade" data-ng-class="{in: active()}" style="margin-top:7px">
<!-- The global progress bar -->
<div class="progress progress-striped active" data-file-upload-progress="progress()"><div class="progress-bar progress-bar-success" data-ng-style="{width: num + '%'}"></div></div>
<!-- The extended global progress state -->
<div class="progress-extended"> </div>
</div>
Nginx Config
user nobody;
worker_processes 1;
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 20;
}
http {
include mime.types;
default_type application/octet-stream;
upstream localapp {
server 127.0.0.1:3000;
}
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
client_max_body_size 4G;
client_body_buffer_size 1024k;
listen 80;
server_name localhost:3000;
#charset koi8-r;
#access_log logs/host.access.log main;
location /jquploadhandle {
upload_max_file_size 0;
upload_pass /post_jquploadhandle.json;
upload_store /store;
upload_state_store /store/states;
upload_store_access user:rw group:rw all:r;
upload_resumable on;
upload_set_form_field file[name] "$upload_file_name";
upload_set_form_field file[content_type] "$upload_content_type";
upload_set_form_field file[filepath] "$upload_tmp_path";
upload_pass_form_field "^theme_id$|^blog_id$|^authenticity_token$|^format$";
upload_cleanup 400 404 499 500-505;
}
location / {
root html;
index index.html index.htm @app;
proxy_pass http://localapp;
}
location @upload {
proxy_pass http://localapp;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}