none
iOS能上传文件到Azure存储吗?! RRS feed

  • 问题

  • 我研究SAS的方式, 获取到一个URL,通过这个URL我可以用C#写一个上传文件的Demo.这个Demo是通过SDK的方式上传的,我无法写出一个web的方式上传(ajax获取到SAS_URL 再post发送文件到SAS_URL的Azure存储)。

    我又去寻找Xamarin for iOS的方法,但找到的都是通过”移动服务“的方式存储数据的例子,没有上传文件到Azure存储的例子。

    或者Windows应用程序demo 存储文件到Azure http://www.windowsazure.cn/documentation/articles/mobile-services-windows-store-dotnet-upload-data-blob-storage   这个方法同样需要SDK,好像最终获取的也SAS_URL方法。

    能给我例子  直接通过SAS_URL上传文件 通过http协议什么的上传文件到 Azure

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>File Uploader</title>
        <script src="jquery.min.js"></script>
     
        <script>
            var maxBlockSize = 256 * 1024;//Each file will be split in 256 KB.
            var numberOfBlocks = 1;
            var selectedFile = null;
            var currentFilePointer = 0;
            var totalBytesRemaining = 0;
            var blockIds = new Array();
            var blockIdPrefix = "block-";
            var submitUri = null;
            var bytesUploaded = 0;
    
            $(document).ready(function () {
                $("#output").hide();
                $("#file").bind('change', handleFileSelect);
                if (window.File && window.FileReader && window.FileList && window.Blob) {
                    // Great success! All the File APIs are supported.
                } else {
                    alert('The File APIs are not fully supported in this browser.');
                }
            });
    
            //Read the file and find out how many blocks we would need to split it.
            function handleFileSelect(e) {
                maxBlockSize = 256 * 1024;
                currentFilePointer = 0;
                totalBytesRemaining = 0;
                var files = e.target.files;
                selectedFile = files[0];
                $("#output").show();
                $("#fileName").text(selectedFile.name);
                $("#fileSize").text(selectedFile.size);
                $("#fileType").text(selectedFile.type);
                var fileSize = selectedFile.size;
                if (fileSize < maxBlockSize) {
                    maxBlockSize = fileSize;
                    console.log("max block size = " + maxBlockSize);
                }
                totalBytesRemaining = fileSize;
                if (fileSize % maxBlockSize == 0) {
                    numberOfBlocks = fileSize / maxBlockSize;
                } else {
                    numberOfBlocks = parseInt(fileSize / maxBlockSize, 10) + 1;
                }
                console.log("total blocks = " + numberOfBlocks);
                var baseUrl = $("#sasUrl").val();
                var indexOfQueryStart = baseUrl.indexOf("?");
                submitUri = baseUrl.substring(0, indexOfQueryStart) + '/' + selectedFile.name + baseUrl.substring(indexOfQueryStart);
                console.log(submitUri);
            }
    
            var reader = new FileReader();
    
            reader.onloadend = function (evt) {
                if (evt.target.readyState == FileReader.DONE) { // DONE == 2
                    var uri = submitUri + '&comp=block&blockid=' + blockIds[blockIds.length - 1];
                    var requestData = new Uint8Array(evt.target.result);
                    $.ajax({
                        url: uri,
                        type: "PUT",
                        data: requestData,
                        processData: false,
                        beforeSend: function (xhr) {
                            xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
                            xhr.setRequestHeader('Content-Length', requestData.length);
                        },
                        success: function (data, status) {
                            console.log(data);
                            console.log(status);
                            bytesUploaded += requestData.length;
                            var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
                            $("#fileUploadProgress").text(percentComplete + " %");
                            uploadFileInBlocks();
                        },
                        error: function (xhr, desc, err) {
                            console.log(desc);
                            console.log(err);
                        }
                    });
                }
            };
    
            function uploadFileInBlocks() {
                if (totalBytesRemaining > 0) {
                    console.log("current file pointer = " + currentFilePointer + " bytes read = " + maxBlockSize);
                    var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
                    var blockId = blockIdPrefix + pad(blockIds.length, 6);
                    console.log("block id = " + blockId);
                    blockIds.push(btoa(blockId));
                    reader.readAsArrayBuffer(fileContent);
                    currentFilePointer += maxBlockSize;
                    totalBytesRemaining -= maxBlockSize;
                    if (totalBytesRemaining < maxBlockSize) {
                        maxBlockSize = totalBytesRemaining;
                    }
                } else {
                    commitBlockList();
                }
            }
    
            function commitBlockList() {
                var uri = submitUri + '&comp=blocklist';
                console.log(uri);
                var requestBody = '<?xml version="1.0" encoding="utf-8"?><BlockList>';
                for (var i = 0; i < blockIds.length; i++) {
                    requestBody += '<Latest>' + blockIds[i] + '</Latest>';
                }
                requestBody += '</BlockList>';
                console.log(requestBody);
                $.ajax({
                    url: uri,
                    type: "PUT",
                    data: requestBody,
                    beforeSend: function (xhr) {
                        xhr.setRequestHeader('x-ms-blob-content-type', selectedFile.type);
                        xhr.setRequestHeader('Content-Length', requestBody.length);
                    },
                    success: function (data, status) {
                        console.log(data);
                        console.log(status);
                    },
                    error: function (xhr, desc, err) {
                        console.log(desc);
                        console.log(err);
                    }
                });
    
            }
            function pad(number, length) {
                var str = '' + number;
                while (str.length < length) {
                    str = '0' + str;
                }
                return str;
            }
        </script>
    </head>
    <body>
        <form>
            <div style="margin-left: 20px;">
                <h1>File Uploader</h1>
                <p>
                    <strong>SAS URI</strong>:
                    <br />
                    <span class="input-control text">
                        <input type="text" id="sasUrl" style="width: 50%"
                               value="" />
                    </span>
                </p>
                <p>
                    <strong>File To Upload</strong>:
                    <br />
                    <span class="input-control text">
                        <input type="file" id="file" name="file" style="width: 50%" />
                    </span>
                </p>
                <div id="output">
    
                    <strong>File Properties:</strong>
                    <br />
                    <p>
                        Name: <span id="fileName"></span>
                    </p>
                    <p>
                        File Size: <span id="fileSize"></span> bytes.
                    </p>
                    <p>
                        File Type: <span id="fileType"></span>
                    </p>
                    <p>
                        <input type="button" value="Upload File" onclick="uploadFileInBlocks()" />
                    </p>
                    <p>
                        <strong>Progress</strong>: <span id="fileUploadProgress">0.00 %</span>
                    </p>
                </div>
            </div>
            <div>
            </div>
        </form>
    </body>
    </html>
    上面的代码是我从网上找的,可调试不过,报403错误


    • 已编辑 Hyposhan 2015年9月14日 9:55
    2015年9月14日 9:53

答案

全部回复

  • 403一般都是禁止访问的错误,请检查你的sas的地址,你也可以尝试使用Azure storage explorer这个工具生成的sas地址在测试一下,以排除sas地址不正确的问题。关于代码onload方法的部分我们主要是使用https://msdn.microsoft.com/en-us/library/azure/dd135726.aspx 这个azure storage rest API的部分来实现的。
    2015年9月15日 0:30
  • 那个SAS_URL 我用asp.net等程序可以上传文件,我可以确认 SAS_URL绝对没有问题。

    Put Block (REST API) 这个文档看不懂啊!。。。

    有没有不封装死的参考代码。

    2015年9月15日 7:41
  • Hi,

    我尝试了下你的代码,获得了403错误,在fiddler工具中错误的详细信息是:"CORS not enabled or no matching rule found for this request.", 我查找到和你类似的代码:http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/,从你的具体错误和文章中可以看出是cors的问题,作者在写博客的时候也指出了当时并不支持CORS访问,不过目前这项功能已经有了,详细请阅读:http://blogs.msdn.com/b/windowsazurestorage/archive/2014/02/03/windows-azure-storage-introducing-cors.aspx, CORS 规则在服务级别设置,因此你需要分别为每个服务(Blob、队列和表)启用或禁用 CORS。默认情况下,对每个服务禁用 CORS。若要启用 CORS,你需要使用版本 2013-08-15 或更高版本设置适当的服务属性,并向服务属性中添加 CORS 规则。有关如何为服务启用或禁用 CORS 以及如何设置 CORS 规则的详细信息,请参阅设置 BLOB 服务属性设置表服务属性设置队列服务属性。更多详细内容,请阅读: https://msdn.microsoft.com/zh-cn/library/azure/dn535601.aspx

    Best Regards,

    Jambor

    如果您想进一步了解Windows Azure, Windows Azure 官网欢迎您的访问 


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.




    2015年9月16日 7:10
    版主
  • 谢谢您的帮助,大概知道怎么做了。

    还得绕回 REST API,好难咯。REST API加密验证用户,我都写不出代码来,下一步没法进行了。

    iOS没有存储这一块没有SDK,准备放弃Azure转投AWS的s3了。

    再次谢谢您的帮助。

    2015年9月17日 11:29
  • Hi,

    我测试过其实你提供的代码是可以work的,只差一步配置个CORS规则,关于配置CORS规则,你完全可以尝试通过一些Azure存储的工具来做,我测试时使用的是Azure Storage Explorer来配置的,下面是我测试时所添加的配置,你可以参考下:

    关于详细的参数设置你也可以参考我第一个回复,在配置完成后我们就可以通过你的代码来上传文件了。

    Jambor

    如果您想进一步了解Windows Azure, Windows Azure 官网欢迎您的访问 


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2015年9月18日 0:59
    版主
  • 太感谢您的回答了,我可以通过ajax上传文件了,现在想通过iOS上传文件,有个疑问:就是域名网址,我该填什么,iOS好像不是在本地虚拟个服务器吧,这样就没有具体的网址了,我不打算用嵌入浏览器窗口的模式开发着这个项目,因为浏览器的上传控件不能随便调用文件

    网址域名可以用*来代替吗?

    再次感谢您的帮助!

    2015年9月18日 3:37
  • Hi,

    从文档上来看我们是可以使用*来代替的,详细文档地址是:https://msdn.microsoft.com/zh-cn/library/azure/dn535601.aspx,你可以使用*号尝试下。

    AllowedOrigins:允许通过 CORS 对存储服务发出请求的源域。源域是从中发出请求的域。请注意,来源必须与用户代理发送到服务的来源完全相同,包括大小写。也可以使用通配符“*”允许所有源域通过 CORS 发出请求。在上面的示例,域http://www.contoso.com 和http://www.fabrikam.com 可以使用 CORS 对服务发出请求。

    Jambor

    如果您想进一步了解Windows Azure, Windows Azure 官网欢迎您的访问 


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    2015年9月18日 4:46
    版主
  • 貌似星号 放在域名里不行啊!
    2015年9月18日 6:49
  • Hi,

    可以肯定的是我们是可以设置’*‘的,之所以出现这个问题可能是工具本身的问题,你可以针对这个问题进行投票:https://azurestorageexplorer.codeplex.com/workitem/9413,如果可以的话,你可以按照这篇文章尝试使用c#来设置:http://blogs.msdn.com/b/windowsazurestorage/archive/2014/02/03/windows-azure-storage-introducing-cors.aspx,下面是主要设置部分的代码:

    private static void ConfigureCors(ServiceProperties serviceProperties)
    {
        serviceProperties.Cors = new CorsProperties();
        serviceProperties.Cors.CorsRules.Add(new CorsRule()
        {
            AllowedHeaders = new List<string>() { "*" },
            AllowedMethods = CorsHttpMethods.Put | CorsHttpMethods.Get | CorsHttpMethods.Head | CorsHttpMethods.Post,
            AllowedOrigins = new List<string>() { "*" },
            ExposedHeaders = new List<string>() { "*" },
            MaxAgeInSeconds = 1800 // 30 minutes
         });
    }

    之后如果有问题也欢迎你开新帖,这样的话会得到更多的回复,同时也会帮助到更多有相同问题的人。

    Best Regards,

    Jambor

    如果您想进一步了解Windows Azure, Windows Azure 官网欢迎您的访问 



    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2015年9月18日 8:13
    版主
  • 不好意思  还得在这个帖子讨论一下。

    中国版的azure 

     private static void ConfigureCorscn(Microsoft.WindowsAzure.StorageClient.Protocol.ServiceProperties serviceProperties)
        {
            serviceProperties.Cors = new CorsProperties();
            serviceProperties.Cors.CorsRules.Add(new CorsRule()
            {
                AllowedHeaders = new List<string>() { "content-type,accept,x-ms-*" },
                AllowedMethods = CorsHttpMethods.Put | CorsHttpMethods.None, // | CorsHttpMethods.Head | CorsHttpMethods.Post,
                AllowedOrigins = new List<string>() { "*" },
                ExposedHeaders = new List<string>() { "x-ms-*" },
                MaxAgeInSeconds = 1800 // 30 minutes
            });
        }

    这样子报错 提示没有定义 Cors 

     serviceProperties.Cors = new CorsProperties();

    国外版按照你的方法已经没问题!是不是我下载的中国本 dll文件库不全啊?

    2015年9月24日 8:19
  • Hi,

    这个问题主要是处在serviceProperties这个对象上,正确的引用参考下图

    请修改serviceProperties的定义类如上图高亮所示。

    Best Regards,

    Jambor

    如果您想进一步了解Windows Azure, Windows Azure 官网欢迎您的访问 


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2015年9月28日 1:55
    版主