AngularJS angular-file-upload cannot upload data t

2019-04-16 13:37发布

问题:

I'm trying to use https://github.com/danialfarid/angular-file-upload to upload an image to my webAPI in a different domain.

My HTML:

<input 
    type="file" 
    ng-file-select="onFileSelect($files)"
    ng-model="imgData" 
    accept="image/*" 
    ng-click="test()" >

My Controller:

app.controller('userController', [ 'removed', '$upload',
function (removed, $upload) {

    $scope.onFileSelect = function ($files) {
        console.log('onFileSelect');  // --------- THIS METHOD DOES NOT FIRE
        $http.post(serviceBase + 'api/person/image', data, {
            withCredentials: true,
            transformRequest: angular.identity
        }).success('ok').error('fail');
    }
    // tried different things from all the resources found online:
    $scope.test = function () {

        // THIS WORKS but how to get the file??
        // successfull call to controller method but unable to retrieve image file inside controller
        $http.post(serviceBase + 'api/person/image', data).then(function (response) {
            return response;
        });

        // unable to call controller method ('Resourse not found', CORS issue?)
        $scope.upload = $upload.upload({
            url: 'person/image', 
            headers: { 'Authorization': 'bearer placeHolderText' },
            file: $scope.imgData,
            ) };

        // unable to call controller method ('Resourse not found', CORS issue?)
        $http.post(serviceBase + 'api/person/image', data, {
            withCredentials: true,
            transformRequest: angular.identity
        }).success('ok').error('fail');}}

API Controller Method:

    [HttpPost()]
    [ActionName("image")]
    [ResponseType(typeof(JObject))]
    public async Task<IHttpActionResult> Postimage(HttpPostedFileBase file)
    {

**Update: Enabling CORS details... (Microsoft.Owin.Cors) **

My Startup.cs:

  public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        ConfigureOAuth(app);

        WebApiConfig.Register(config);
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(config);
    }

    public void ConfigureOAuth(IAppBuilder app)
    {
        //use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ExternalCookie);
        OAuthBearerOptions = new OAuthBearerAuthenticationOptions();

        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() {

            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
            Provider = new SimpleAuthorizationServerProvider(),
            RefreshTokenProvider = new SimpleRefreshTokenProvider()
        };

It is most likely that this is a CORS issue because I can post to that controller method using $HTTP.Post. I have enabled CORS on server. I have been reading and trying things for two days and I've hit a brick wall, any suggestions/recommendations are greatly appreciated.

Update 2:

Another day of research/trial and error:

I can get this to post:

        $scope.upload = $upload.upload({
            url: 'http://localhost:26264/api/person/image', //upload.php script, node.js route, or servlet url
            file: $scope.imgData,
            transformRequest: angular.identity,
            headers: { 'Content-Type': undefined }

but now I get '415 (Unsupported Media Type)'.. details from fiddler:

"The request entity's media type 'multipart/form-data' is not supported for this resource.","exceptionMessage":"No MediaTypeFormatter is available to read an object of type 'HttpPostedFileBase' from content with media type 'multipart/form-data'."

回答1:

I ended up using ng-flow, the Images Sample helped in getting setup. I also used this to find out how to read the data in my controller, and finally this to save my file. Final solution:

Controller:

    [HttpPost()]
    [ActionName("image")]
    [ResponseType(typeof(JObject))]
    public async Task<IHttpActionResult> Postimage()
    {
        // Check if the request contains multipart/form-data.
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

        string root = HttpContext.Current.Server.MapPath("~/Content/Images/User");
        var provider = new MultipartFormDataStreamProvider(root);

        try
        {
            // Read the form data.
            await Request.Content.ReadAsMultipartAsync(provider);

            // This illustrates how to get the file names.
            foreach (MultipartFileData file in provider.FileData)
            {
                //Console.WriteLine(file.Headers.ContentDisposition.FileName);
                //Trace.WriteLine("Server file path: " + file.LocalFileName);
                if (File.Exists(Path.Combine(root, "test.jpg")))
                    File.Delete(Path.Combine(root, "test.jpg"));

                File.Move(file.LocalFileName, Path.Combine(root, "test.jpg"));
                return Ok();
            }
        }
        catch (System.Exception e)
        {
        }
        return Ok();
    }

Angular:

app.config(['flowFactoryProvider', function (flowFactoryProvider) {
    flowFactoryProvider.defaults = {
        target: 'myURL',
        permanentErrors: [404, 500, 501],
        maxChunkRetries: 1,
        chunkRetryInterval: 5000,
        simultaneousUploads: 4,
        singleFile: true
    };
    flowFactoryProvider.on('catchAll', function (event) {
        console.log('catchAll', arguments);
    });
    // Can be used with different implementations of Flow.js
    // flowFactoryProvider.factory = fustyFlowFactory;
}]);

HTML:

<div class="form-horizontal" role="form" flow-init
   flow-file-added="!!{png:1,gif:1,jpg:1,jpeg:1}[$file.getExtension()]"
   flow-files-submitted="$flow.upload()">

<span class="btn-success" flow-btn>Upload Image</span>
</div>