GVKun编程网logo

使用AngularJS和ASP.NET Web API上传/下载字节数组(angularjs上传文件)

5

想了解使用AngularJS和ASP.NETWebAPI上传/下载字节数组的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于angularjs上传文件的相关问题,此外,我们还将为您介绍关于An

想了解使用AngularJS和ASP.NET Web API上传/下载字节数组的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于angularjs上传文件的相关问题,此外,我们还将为您介绍关于AngularJS + ASP.NET Web API + ASP.NET MVC身份验证、angularjs – Angular JS MVC Web API模型/参数不绑定.NET Core、angularjs – Angular.js和Amazon S3 – 如何上传文件?、angularjs – asp.net web api 2 CORS和身份验证授权配置的新知识。

本文目录一览:

使用AngularJS和ASP.NET Web API上传/下载字节数组(angularjs上传文件)

使用AngularJS和ASP.NET Web API上传/下载字节数组(angularjs上传文件)

我花了几天的时间研究和研究用于上传/下载byte的解决方案。我已经接近了,但是还有一个问题似乎在我的AngularJS代码块中。

在陈述问题之前,这里有一些背景信息来设置上下文。

  1. 我试图创建一个通用的客户端/服务器接口来上载和下载byte [],它们被用作专有服务器数据库的一部分。
  2. 我在客户端上使用TypeScript,AngularJS,JavaScript和Bootstrap CSS创建单页应用程序(SPA)。
  3. 我在服务器上使用ASP.NET Web API / C#。

正在开发SPA来替代在Silverlight中开发的现有产品,因此将SPA限制为现有系统要求。SPA还需要针对各种设备(从移动设备到台式机)和主要操作系统。

借助一些在线资源(在下面列出),我的大部分代码都可以正常工作。我正在使用下面的Byte Rot链接中的byte []的异步多媒体格式化程序。

http://byterot.blogspot.com/2012/04/aspnet-web-api-series-
part-5.html

从ASP.NET WebAPI中的控制器返回二进制文件

  1. 我正在使用转换为Uint8Array的jpeg作为客户端上的测试用例。
  2. 实际的系统字节数组将包含压缩为预定义数据包的混合内容。但是,我需要能够处理任何有效的字节数组,以便图像是有效的测试用例。
  3. 使用下面显示的客户端和服务器代码以及字节循环格式化程序将数据正确传输到服务器(未显示,但可在其网站上找到)。
  4. 我已经验证了jpeg作为字节[]与字符串参数元数据一起在服务器上正确接收。
  5. 我已经使用Fiddler来验证是否将正确的响应发送回了客户端。
    • 大小正确
    • 该图像在Fiddler中可见。
  6. 我的问题是,以下所示的Angular客户端代码中的服务器响应不正确。

    • 不正确的 意思是我的 大小错误(〜10K与〜27.5K), 并且 对于UintArray构造函数 ,它 不被识别为有效值 。当我将光标放在下面的客户端代码中显示的返回的“响应”上时,Visual Studio显示JFIF,但是没有其他可见的内容指示符。

/服务器代码/ 在[FromBody] byte[]之后将丢失的项目添加到代码中

public class ItemUploadController : ApiController{ 
[AcceptVerbs("Post")]
    public HttpResponseMessage Upload(string var1,string var2,[FromBody]byte[] item){
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new MemoryStream(item);
        result.Content = new StreamContent(stream);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        return result;
    }
}

/ 示例客户代码 /

我从代码中省略的唯一一件事是实际的变量参数。

$http({
url: 'api/ItemUpload/Upload',method: 'POST',headers: { 'Content-Type': 'application/octet-stream' },// Added per Byte Rot blog...
    params: {
        // Other params here,including string metadata about uploads
        var1: var1,var2: var2
    },data: new Uint8Array(item),// arrybuffer must be lowecase. Once changed,it fixed my problem.
responseType: 'arraybuffer',// Added per http://www.html5rocks.com/en/tutorials/file/xhr2/
transformRequest: [],})
.success((response,status) => {
    if (status === 200) {
        // The response variable length is about 10K,whereas the correct Fiddler size is ~27.5K.
        // The error that I receive here is that the constructor argument in invalid.
        // My guess is that I am doing something incorrectly with the AngularJS code,but I
        // have implemented everything that I have read about. Any thoughts???
        var unsigned8Int = new Uint8Array(response);
        // For the test case,I want to convert the byte array back to a base64 encoded string
        // before verifying with the original source that was used to generate the byte[] upload.
        var b64Encoded = btoa(String.fromCharCode.apply(null,unsigned8Int));
        callback(b64Encoded);
    }
})
.error((data,status) => {
    console.log('[ERROR] Status Code:' + status);
});

/ ******** ** /

任何帮助或建议,将不胜感激。

谢谢…

编辑以包含更多诊断数据

首先,我使用angular.isArray函数确定响应值不是数组,我认为应该是。

其次,我使用以下代码询问响应,该响应似乎是不可见的字符串。前导字符似乎不对应于图像字节数组代码中的任何有效序列。

var buffer = new ArrayBuffer(response.length);
var data = new Uint8Array(buffer);
var len = data.length,i;
for (i = 0; i < len; i++) {
    data[i] = response[i].charCodeAt(0);
}

实验结果

我通过在下载的服务器上创建0到255之间的字节数组值来进行实验。AngularJS客户端正确接收了前128个字节(即0,1,…,126,127),但其余值在Internet
Explorer
11中为65535,在Chrome和Firefox中为65533。Fiddler显示通过网络发送了256个值,但是AngularJS客户端代码中仅收到217个字符。如果我仅使用0-127作为服务器值,那么一切似乎都可以正常工作。我不知道是什么原因引起的,但是客户端响应似乎更符合带符号的字节,我认为这是不可能的。

来自服务器的Fiddler
Hex数据显示256个字节,其值的范围是00,01,…,EF,FF,这是正确的。如前所述,我可以返回图像并在Fiddler中正确查看它,因此Web
API服务器接口可用于POST和GET。

我正在尝试香草XMLHttpRequest,看看我可以在AngularJS环境之外工作。

XMLHttpRequest测试更新

我已经能够确认香草XMLHttpRequest是否可以与GET服务器配合使用,并且能够返回正确的字节码和测试图像。

好消息是我可以在AngularJS周围乱搞,以使系统正常工作,但坏消息是我不喜欢这样做。我希望与Angular一起进行所有客户端服务器通信。

我将在Stack Overflow上打开一个单独的问题,该问题仅处理AngularJS遇到的GET byte
[]问题。如果可以解决,则将出于历史目的使用解决方案更新此问题,以帮助他人。

更新资料

Google网上论坛的Eric Eslinger给我发送了一个小段代码,突出显示responseType应该为“
arraybuffer”(全部小写)。我更新了上面的代码块以显示小写值并添加了注释。

谢谢…

AngularJS + ASP.NET Web API + ASP.NET MVC身份验证

AngularJS + ASP.NET Web API + ASP.NET MVC身份验证

我是AngularJS的新手,正在尝试为我的新Web应用程序对其进行评估。

需求:

我将有一个ASP.NET Web API,它将从Android,iPhone和Web应用程序(ASP.NET MVC)中使用。ASP.NET
Identity将在Web API中实现。这三个应用程序都将调用Web API的login方法来获取auth令牌。

问题:

我的问题是当Angular进行调用以获取HTML模板/视图,JavaScript文件时,如何获得ASP.NET MVC 服务器端身份验证
工作(与Web API同步,因此我不必分别登录ASP.NET
MVC)或其他资源。我在AngularJS上浏览了许多文章和博客,但仍然找不到适合我要求的安全模型。

可能的解决方案:

将登录调用直接调用ASP.NET MVC应用程序而不是Web API是一个好主意,并且ASP.NET MVC应用程序将调用Web
API进行登录,并在进行身份验证之后,将auth令牌保存在会话中并创建一个 FormsAuthentication cookie
和cookie数据中的数据将保存加密的auth令牌。此外,在HTML的 ng-init 中将 auth令牌
设置为AngularJS范围内的令牌。现在,当AngularJS尝试调用ASP.NET
MVC应用程序以获取HTML时,然后通过将cookie中解密的数据与会话中的auth数据进行匹配来对用户进行身份验证/授权。另外,AngularJS将
在标头中 发送 auth令牌,以 直接 调用Web API方法 ,以用于随后通过Web API进行数据操作的所有后续调用。

angularjs – Angular JS MVC Web API模型/参数不绑定.NET Core

angularjs – Angular JS MVC Web API模型/参数不绑定.NET Core

我正在使用带有TypeScript和ASP.NET Core MVC / API的Angular JS.

我有一个apiService来处理对服务器的所有POST和GET请求,如下所示:

module TBApp {

    export class apiService {

        static $inject = ['$http','notificationService'];

        constructor(private $http,private notificationService: notificationService) {

        }

        get(url,config,success,failure) {

            return this.$http.get(url,config)

                .then(result => { this.handleResponse(result,success); },result => { this.handleError(result,failure) });
        }

        post(url,data,failure) {

            return this.$http.post(url,data)
                .then(result => { this.handleResponse(result,failure) });
        }

        handleResponse(result,success) {

            alert('success');
            success(result);

        }

        handleError(result,failure) {

            if (result.status === '401') {

                this.notificationService.displayError('Authentication required.');
                //this.$rootScope.prevIoUsstate = this.$location.path();
                //this.$location.path('/login');

            }
            else if (failure !== null) {
                failure(result);
            }
        }
    }
}

现在,当我发送此请求时:

onCompanyChanged(selectedCompany,model,companyName) {

        this.apiService.post('/api/Dashboard/GetAssetListByCompany',{ companyId: selectedCompany.id },response => {

                this.assetListviewmodel = response.data.data;


            },response => {
            this.notificationService.displayError(response.data.message);
        });
    }

它没有绑定控制器中的companyId

这是控制器:

[Route("api/[controller]")]
    public class DashboardController : BaseController
    {
        [HttpPost]
        [Route("GetAssetListByCompany")]
        public IActionResult GetAssetListByCompany([FromBody]int companyId)
        {
            return CreateJsonResult(() =>
            {
                if (companyId == 0) { return new xPTJsonResult(null,xPTStatusCodesEnum.Success,"Company Id is 0"); }

               //var treeModel = _dashboardProvider.GetTreeModelByCompany(companyId,usermodel);

                return new xPTJsonResult(null,"Loaded assets successfully");

            });
        }

}

即使我在浏览器中检查了请求,也表明companyId在Payload中.

enter image description here

NOTE: The same function works when I post a viewmodel

编辑

在上面的场景中,我只将一个参数传递给控制器​​,但在某些情况下,我希望能够在不使用viewmodel的情况下传递2或3个参数.

例如

public IActionResult GetAssetListByCompany([FromBody]int companyId,[FromBody]int assetId)
{....

要么

public IActionResult GetAssetListByCompany([FromBody]int companyId,[FromBody]int assetId,[FromBody]bool canEdit = false)
    {.....

然后在客户端我可以这样做:

this.apiService.post('/api/Dashboard/GetAssetListByCompany',{ companyId: selectedCompany.id,assetId: 123 }.....

要么

this.apiService.post('/api/Dashboard/GetAssetListByCompany',canEdit: true,assetId: 22 }....

解决方法

这里最好的方法是遵循HTTP准则并将操作从POST更改为GET,因为您不修改任何数据.这很简单,仍然可以使用URI通过您的请求发送数据.

MVC改变了

有关各种选项,请参阅Model Binding,此处的最佳方法是基于查询字符串进行绑定,因为您只需要一个基本类型.如果您有一个基本类型数组仍然可以绑定到查询字符串,则查询字符串变量名称将为每个值重复一次.

因此,我们所做的唯一更改是指定参数来自查询字符串,并且它与Http Get请求而不是Post相关联.

[Route("api/[controller]")]
public class DashboardController : BaseController
{
    [HttpGet] // change to HttpGet
    [Route("GetAssetListByCompany")]
    public IActionResult GetAssetListByCompany([FromQuery]int companyId) // use FromQuery
    {
        return CreateJsonResult(() =>
        {
            if (companyId == 0) { return new xPTJsonResult(null,"Company Id is 0"); }

           //var treeModel = _dashboardProvider.GetTreeModelByCompany(companyId,usermodel);

            return new xPTJsonResult(null,"Loaded assets successfully");

        });
    }
}

AngularJS发生了变化

我们扩展apiService以允许使用HttpGet传递调用数据.这可以使用params on the $http call完成,它将使用名称作为查询字符串值名称和值作为值部分,根据传入的数据动态创建URL.

export class apiService {
    /* all other code is left as is,just change the get method to also accept data via the params. If null is passed in then it is ignored. */
    get(url,failure) {
        return this.$http({
            url: url,config: config,params: data,method: "GET"
            })
            .then(result => { this.handleResponse(result,failure) });
    }
}

在通话中我们只需要从post更改为get,它应该可以工作.

// only change from post to get
onCompanyChanged(selectedCompany,companyName) {
    this.apiService.get('/api/Dashboard/GetAssetListByCompany',response => {
            this.assetListviewmodel = response.data.data;
        },response => {
        this.notificationService.displayError(response.data.message);
    });
}

编辑 – 这很灵活

更重要的是,这种设计在角度方面是灵活的.如果您扩展MVC操作或具有采取其他参数的各种操作,则无需执行任何其他更改即可运行.例:

[HttpGet]
[Route("GetSomethingElseFromServer")]
public IActionResult GetSomethingElseFromServer([FromQuery]int companyId,[FromQuery]string assetName,[FromQuery]string companyModelNumber) // use FromQuery

对你的角度api的调用将是

this.apiService.get('/api/Dashboard/GetSomethingElseFromServer',{ companyId: companyId,assetName: somePassedInAssetNameVar,companyModelNumber: somePassedInModelNumber }

编辑 – 您也可以发送数组

要回答关于如何将多个基元类型作为数组发送的问题,您可以这样做.同样,这假设它不是您要发送的复杂类型,但是,例如,公司ID列表.

c#代码

[HttpGet]
[Route("GetAssetListByCompany")]
public IActionResult GetAssetListByCompany([FromQuery]int[] companyIds) // use an array of int ie. int[]. i changed the variable name to make it clear there can be more than 1

Angular调用,注意没有必要更改服务

onCompanyChanged(selectedCompany,{ "companyIds[]": [id1,id2,id3] },// note the name is Now enclosed in quotes,made plural,and includes []. The value is an array
        response => {
            this.assetListviewmodel = response.data.data;
        },response => {
        this.notificationService.displayError(response.data.message);
    });
}

编辑 – 如果你想要POST

您目前只发送一个原始字段,因此POST中的MVC框架无法正确反序列化.您需要将参数包装在视图模型中,将其作为查询字符串部分发送,或将其作为表单字段值发送.这是带有查询字符串部分的POST,它可以正常工作.

选项1

将其附加到URL

[HttpPost] // change to HttpGet
[Route("GetAssetListByCompany")]
public IActionResult GetAssetListByCompany([FromQuery] int companyId) // use FromQuery

角度呼叫

this.apiService.post('/api/Dashboard/GetAssetListByCompany/?companyId=' + selectedCompany.id +,null,// the rest of the code remains unchanged so I did not include it

选项2

扩展apiService以获取params对象,以便它可以构建您的查询.无论哪种方式,你都会遇到调用者不得不对http调用有所了解.

this.apiService.post('/api/Dashboard/GetAssetListByCompany',{companyId: selectedCompany.id},// the rest of the code remains unchanged so I did not include it

post(url,params,failure) {
    return this.$http({
        url: url,data: data,params: params,method: "POST"
        })
        .then(result => { this.handleResponse(result,failure) });
}

选项3

更新视图模型以采用复杂类型,这不需要更改角度代码.

public class ListByCompanyModel {
    public int CompanyId {get;set;}
}

[HttpPost] // change to HttpGet
[Route("GetAssetListByCompany")]
public IActionResult GetAssetListByCompany([FromBody] ListByCompanyModel model) // use FromQuery

angularjs – Angular.js和Amazon S3 – 如何上传文件?

angularjs – Angular.js和Amazon S3 – 如何上传文件?

我在Angular.js中有一个应用程序.事实上,我在我的旧网站上做了更新,改为Angular.

在旧版本中,我使用Uploadfy jquery组件来在Amazon S3中上传.但现在,有了Angular,我无法使用它.

我想使用指令“ngUpload”.但我不知道该怎么做.
有人可以帮我吗?

解决方法

您可以使用 angular-file-upload轻量级角度指令,该指令支持文件进度和文件丢弃.

您可以在此处关注Amazon S3问题,其中包含示例代码,以及如何将所有这些数据与文件上载一起发送:
https://github.com/danialfarid/angular-file-upload/issues/23

S3上传应该适用于上面的1.1.1版.

另一个相关问题:https://github.com/danialfarid/angular-file-upload/issues/23

angularjs – asp.net web api 2 CORS和身份验证授权配置

angularjs – asp.net web api 2 CORS和身份验证授权配置

我已经创建了一个具有个人帐户安全性的asp.net web api 2服务.我试图按照这个例子将其称为AngularJs:
http://www.codeproject.com/Articles/742532/Using-Web-API-Individual-User-Account-plus-CORS-En
无法让它工作,所以从这里添加了一些配置:
How to make CORS Authentication in WebAPI 2?

并且无法通过此错误:
XMLHttpRequest无法加载’serverRegisterUrl’.
‘Access-Control-Allow-Origin’标头包含多个值’clientUrl,*,*’,
但只允许一个.因此,不允许来源’clientUrl’访问.

我不明白这个错误信息.我认为Access-Control-Allow-Origin字符串意味着允许原始clientUrl,所有标题,所有方法

我不明白这个问题.如果我应该只在某处指定原点,我不知道那是哪里.

我在Microsoft Azure上运行此操作,并使用vs express for web 2013 update 2以防万一.

不幸的是,我不得不从错误消息中取出我的链接,因为我需要至少在这里发布信誉10才能在一个问题中发布超过2个链接.

解决方法

我得到了它的工作,我认为它归结为配置.
Web.config:没有“Access-Control-Allow-Origin”customHeaders节点

Startup.Auth.cs:
//这必须首先拦截/ Token请求
app.UseCors(CorsOptions.AllowAll);

//使应用程序能够使用承载令牌对用户进行身份验证
app.USEOAuthBearerTokens(OAuthOptions);

WebApiConfig.cs :(不在这里启用cors)
// var cors = new EnableCorsAttribute(“*”,“*”,“*”);
//config.EnableCors(cors);

AccountController.cs:
GetExternalLogin方法的属性:
[EnableCors(起源:“*”,标题:“*”,方法:“*”)]

我认为这是我目前的整个CORS配置.

关于使用AngularJS和ASP.NET Web API上传/下载字节数组angularjs上传文件的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于AngularJS + ASP.NET Web API + ASP.NET MVC身份验证、angularjs – Angular JS MVC Web API模型/参数不绑定.NET Core、angularjs – Angular.js和Amazon S3 – 如何上传文件?、angularjs – asp.net web api 2 CORS和身份验证授权配置等相关知识的信息别忘了在本站进行查找喔。

本文标签: