Javascript 当我使用XMLHttpRequest和SAS将映像放入azure blob存储时,格式不正确

Javascript 当我使用XMLHttpRequest和SAS将映像放入azure blob存储时,格式不正确,javascript,azure,xmlhttprequest,blob,storage,Javascript,Azure,Xmlhttprequest,Blob,Storage,我在SPA应用程序中设置了将文件发送到Azure Blob存储的功能 为此,我使用了XMLHttpRequest和FormData(我的用户在我公司管理的计算机上,所有人都可以访问HTML5)。   为了管理安全性,发送每个文件之前都会调用Web Api的方法以获得共享访问签名 我将文件的内容类型以及其他信息转发到标题 一切都会变得更好,文件被正确地发送并保存在Azure Blob存储中,但在传输过程中,图像文件似乎被“更改” 它们都很好,我可以下载它们并在下载后阅读,但我不能直接从img标签打

我在SPA应用程序中设置了将文件发送到Azure Blob存储的功能

为此,我使用了XMLHttpRequest和FormData(我的用户在我公司管理的计算机上,所有人都可以访问HTML5)。   为了管理安全性,发送每个文件之前都会调用Web Api的方法以获得共享访问签名

我将文件的内容类型以及其他信息转发到标题

一切都会变得更好,文件被正确地发送并保存在Azure Blob存储中,但在传输过程中,图像文件似乎被“更改”

它们都很好,我可以下载它们并在下载后阅读,但我不能直接从img标签打开它们

另一方面,如果我通过Microsoft Azure Storage Explorer发送相同的图像文件,则没有问题,图像在img标记中可以很好地识别。 然而,在另一种情况下,内容类型被标记为“image/jpeg”。唯一值得注意的区别是,这两封邮件之间的MD5不同,而它是相同的原始文件

从我的发现来看,通过XMLHttpRequest发送时,似乎在文件的开头和结尾添加了文本

我解释我的代码,以便您可以指导我: 注1:我使用typescript(但javascript解决方案适合我)和Promise。 注2:我已解决所有CORS问题。 注3:我使用的是Azure存储模拟器,但我尝试使用普通的Azure服务,问题是相同的

以下是Chrome中图像中添加的文本:

------WebKitFormBoundaryKj5cK88faAwJd4av
Content-Disposition: form-data; name="file1"; filename="test.jpg"
Content-Type: image/jpeg

[image content]

------WebKitFormBoundaryKj5cK88faAwJd4av--
我的Web Api:

[Route(@"api/Storage/FileSas/Customers/{id:int}")]
public async Task<IHttpActionResult> GetFileSas(int id, string fileName, long? fileSize = 0, string contentType = null)
{
    if (string.IsNullOrWhiteSpace(fileName))
        this.ModelState.AddModelError("fileName", "File name i");

    if (!fileSize.HasValue || fileSize.Value > maxFileSize)
        this.ModelState.AddModelError("fileSize", "File size exceeded");

    if (!this.ModelState.IsValid)
        return BadRequest(this.ModelState);

    var serverUrl = ConfigurationManager.AppSettings[SERVER_URL];
    var container = ConfigurationManager.AppSettings[CONTAINER_NAME];

    SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy()
    {
        Permissions = SharedAccessBlobPermissions.Write,
        SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-60),
        SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(60),
    };

    CloudBlockBlob blobFile = blobContainer.GetBlockBlobReference(Path.Combine("customers", id.ToString(), fileName));



    var exists = await blobFile.ExistsAsync();
    if (exists)
    {
        await blobFile.SnapshotAsync();
    }

    var signature = blobFile.GetSharedAccessSignature(policy);

    return Content<string>(HttpStatusCode.Created, Path.Combine(serverUrl, container, blobFile.Name + signature));
}
[路由(@“api/Storage/FileSas/Customers/{id:int}”)]
公共异步任务GetFileSas(int-id,字符串文件名,long?fileSize=0,string-contentType=null)
{
if(string.IsNullOrWhiteSpace(文件名))
this.ModelState.AddModelError(“文件名”、“文件名i”);
如果(!fileSize.HasValue | | fileSize.Value>maxFileSize)
this.ModelState.AddModelError(“文件大小”,“超出文件大小”);
如果(!this.ModelState.IsValid)
返回BadRequest(this.ModelState);
var serverUrl=ConfigurationManager.AppSettings[SERVER_URL];
var container=ConfigurationManager.AppSettings[container_NAME];
SharedAccessBlobPolicy策略=新的SharedAccessBlobPolicy()
{
权限=SharedAccessBlobPermissions.Write,
SharedAccessStartTime=DateTime.UtcNow.AddMinutes(-60),
SharedAccessExpiryTime=DateTime.UtcNow.AddMinutes(60),
};
CloudBlockBlob blobFile=blobContainer.GetBlockBlobReference(Path.Combine(“customers”,id.ToString(),fileName));
var exists=await blobFile.ExistsAsync();
如果(存在)
{
等待blobFile.SnapshotAsync();
}
var signature=blobFile.GetSharedAccessSignature(策略);
返回内容(HttpStatusCode.Created,Path.Combine(serverUrl,container,blobFile.Name+签名));
}
我的打字脚本文件:

            context.Storage.getFileSas(customerId, file)
                .then((response: Interfaces.Result<string>) => {

                    let sasUrl = response.Data;

                    let formData = new FormData();

                    formData.append("file1", file, file.name);

                    var xhr = new XMLHttpRequest();

                    xhr.upload.onprogress = (event) => {
                        if (event.total > 0)
                            this.Progress(event.loaded * 100 / event.total);
                    };

                    xhr.onloadstart = function (e) {
                    }

                    xhr.onloadend = (e) => {
                        this.Progress(0);
                    }


                    xhr.open("PUT", sasUrl, true);
                    xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
                    xhr.setRequestHeader('Content-Type', file.type);
                    xhr.setRequestHeader('x-ms-blob-content-type', file.type);                
                    xhr.setRequestHeader('x-ms-version', "2016-05-31");


                    xhr.setRequestHeader('x-ms-meta-CustomerId', customerId);
                    xhr.setRequestHeader('x-ms-meta-UserId', context.User.User.Id.toString());
                    xhr.setRequestHeader('x-ms-meta-UserName', context.User.User.Name);


                    xhr.send(formData);
                })
        })).catch((error) => {
            console.log(error);
        });
context.Storage.getfileas(customerId,文件)
.然后((响应:Interfaces.Result)=>{
让sasUrl=response.Data;
设formData=new formData();
formData.append(“file1”,file,file.name);
var xhr=new XMLHttpRequest();
xhr.upload.onprogress=(事件)=>{
如果(事件总数>0)
进度(event.loaded*100/事件总数);
};
xhr.onloadstart=函数(e){
}
xhr.onloadend=(e)=>{
这是进步(0);
}
xhr.open(“PUT”,sasUrl,true);
setRequestHeader('x-ms-blob-type','BlockBlob');
setRequestHeader('Content-Type',file.Type);
xhr.setRequestHeader('x-ms-blob-content-type',file.type);
xhr.setRequestHeader(“x-ms-version”,“2016-05-31”);
xhr.setRequestHeader('x-ms-meta-CustomerId',CustomerId);
setRequestHeader('x-ms-meta-UserId',context.User.User.Id.toString());
setRequestHeader('x-ms-meta-UserName',context.User.User.Name);
xhr.send(formData);
})
})).catch((错误)=>{
console.log(错误);
});
文件来源:

 let fileInputElement1: HTMLInputElement = <HTMLInputElement>document.getElementById("file1");

 let file = fileInputElement1.files[0];
让fileInputElement1:HTMLInputElement=document.getElementById(“file1”);
让file=fileInputElement1.files[0];
我的HTML部分:(我正在使用knockout)


发送
如果有人有主意

谢谢,这是事先准备好的


PS:sasUrl是这样的:

感谢Gaurav Mantri,他把我指到右边,这里是我的修改(只是因为我使用了typescript):

context.Storage.getfileas(customerId,文件)
.然后((响应:Interfaces.Result)=>{
让sasUrl=response.Data;
var xhr=new XMLHttpRequest();
xhr.upload.onprogress=(事件)=>{
如果(事件总数>0)
进度(event.loaded*100/事件总数);
};
xhr.onloadstart=函数(e){
}
xhr.onloadend=(e)=>{
这是进步(0);
}
let reader=new FileReader();
reader.readAsArrayBuffer(文件);
reader.onloadend=(事件)=>{
让target=event.target;
if(target.readyState==reader.DONE){
var requestData=newuint8array(target.result);
xhr.open(“PUT”,sasUrl,true);
xhr.responseType=“blob”;
<form method="put" target="_blank" enctype="multipart/form-data">
                <input type="file" name="name" value="" id="file1" />
                <button data-bind="click:send"> Send</button>
</form>
  context.Storage.getFileSas(customerId, file)
            .then((response: Interfaces.Result<string>) => {

                let sasUrl = response.Data;

                var xhr = new XMLHttpRequest();

                xhr.upload.onprogress = (event) => {
                    if (event.total > 0)
                        this.Progress(event.loaded * 100 / event.total);
                };

                xhr.onloadstart = function (e) {
                }

                xhr.onloadend = (e) => {
                    this.Progress(0);
                }


                let reader = new FileReader();

                reader.readAsArrayBuffer(file);

                reader.onloadend = (event) => {
                        let target = <FileReader>event.target;

                        if (target.readyState == reader.DONE) {

                            var requestData = new Uint8Array(target.result);

                            xhr.open("PUT", sasUrl, true);
                            xhr.responseType = "blob";
                            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                            xhr.setRequestHeader('X-File-Name', file.name);
                            xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
                            xhr.setRequestHeader('Content-Type', file.type || 'application/octet-stream');
                            xhr.setRequestHeader('x-ms-blob-content-type', file.type || 'application/octet-stream');
                            xhr.setRequestHeader('x-ms-version', "2016-05-31");


                            xhr.setRequestHeader('x-ms-meta-CustomerId', customerId);
                            xhr.setRequestHeader('x-ms-meta-UserId', context.User.Id.toString());
                            xhr.setRequestHeader('x-ms-meta-UserName', context.User.Name);


                            xhr.send(requestData);
                        }
                    }
            })
    })).catch((error) => {
        console.log(error);
    });