Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript FormData()文件上传到S3在Chrome中工作,但在Safari中不工作_Javascript_File Upload_Amazon S3_Safari - Fatal编程技术网

Javascript FormData()文件上传到S3在Chrome中工作,但在Safari中不工作

Javascript FormData()文件上传到S3在Chrome中工作,但在Safari中不工作,javascript,file-upload,amazon-s3,safari,Javascript,File Upload,Amazon S3,Safari,在使用web应用程序时,我会将图像文件直接从浏览器发送到S3存储桶。这在Chrome中运行良好,但在Safari中没有错误,但代码最终将一个空文件上传到S3存储桶。一切基本上看起来都在Safari中工作,S3服务器甚至返回一个204成功的http响应,文件看起来像在bucket中(但大小为0字节) 我正在调试,blobData在Chrome中的尺寸为55747,但在Safari中,对于同一图像,只有47560。另外,我在网络部分dev tools中发现了与此稍有不同的地方: 铬-工作(204响应

在使用web应用程序时,我会将图像文件直接从浏览器发送到S3存储桶。这在Chrome中运行良好,但在Safari中没有错误,但代码最终将一个空文件上传到S3存储桶。一切基本上看起来都在Safari中工作,S3服务器甚至返回一个
204
成功的http响应,文件看起来像在bucket中(但大小为0字节)

我正在调试,
blobData
在Chrome中的尺寸为55747,但在Safari中,对于同一图像,只有47560。另外,我在网络部分dev tools中发现了与此稍有不同的地方:

铬-工作(204响应具有正尺寸~534B):

Safari-不使用空文件(大小列仅显示虚线)

以下是JS上传代码:

    function uploadFile(data_url, s3Data, url, filename, id, thumbnail_url){
        var xhr = new XMLHttpRequest();
        xhr.open("POST", s3Data.url);

        var postData = new FormData();
        for(key in s3Data.fields){
            postData.append(key, s3Data.fields[key]);
        }

        var blobData = dataURItoBlob(data_url);

        postData.append('file', new File([blobData], filename));

        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4){
                if(xhr.status === 200 || xhr.status === 204){
                    setTimeout(function(){

                        $('#photo_container').append('<div id="image_container_'+id+'" class="hover-card mdl-cell--3-col-desktop mdl-cell--2-col-tablet mdl-cell--2-col-phone mdl-shadow--2dp"></div>');

                        $('.star-image').unbind('click').click( star_image_click );
                        $('.close-image').unbind('click').click(remove_image_click);
                        loading_files -= 1;
                        if ( loading_files == 0 ) {
                            $('#photo_load_spinner').removeClass('is-active');
                            $('#photo_load_text').text("");
                        }else{
                            $('#photo_load_text').text(loading_files+" files loading.  Please wait.");
                        }

                    }, 1000);


                }else{
                    alert("Could not upload file. "+xhr.responseText);
                }
            }
        };
        xhr.send(postData);
    }

    function dataURItoBlob(dataURI) {
        var binary = atob(dataURI.split(',')[1]);
        var array = [];
        for(var i = 0; i < binary.length; i++) {
            array.push(binary.charCodeAt(i));
        }
        return new Blob([new Uint8Array(array)], {type: 'image/png'});
    }

我记得Safari对FormData对象的支持有限,例如:


我们可以调整图像文件的大小并上传到服务器。在Chrome和Safari上测试,两者都很好

fileChange() {

    var fileInputTag = document.getElementById("myFile");

    if ('files' in fileInputTag) {
        if (fileInputTag.files.length > 0) {

            var file = fileInputTag.files[0];

            var type = 'image/jpeg',
            maxWidth = 800,
            maxHeight = 600,
            quality = 0.5,
            ratio = 1,

            canvas = document.createElement('canvas'),
            context = canvas['getContext']('2d'),
            canvasCopy = document.createElement('canvas'),
            copyContext = canvasCopy.getContext('2d'),

            img = new Image();

            img.onload = function () {
              if (img.width > maxWidth) {
                ratio = maxWidth / img.width;
              } else if (img.height > maxHeight) {
                ratio = maxHeight / img.height;
              }

              canvasCopy.width = img.width;
              canvasCopy.height = img.height;
              copyContext.drawImage(img, 0, 0);
              canvas.width = img.width * ratio;
              canvas.height = img.height * ratio;
              context.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);

              canvas.toBlob((blob) =>  {
                blob['name'] = file.name.split('.')[0] + '.jpeg';

                var formData:FormData = new FormData();
                formData.append('uploadFile', blob, blob.name);

                // do upload here

              }, type, quality);

            };

            img.src = URL.createObjectURL(file);

        }
    }
}
将其添加到index.html或在执行上述脚本之前执行它

if (!HTMLCanvasElement.prototype.toBlob) {
    Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
    value: function (callback, type, quality) {

        var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
            len = binStr.length,
            arr = new Uint8Array(len);

        for (var i = 0; i < len; i++ ) {
        arr[i] = binStr.charCodeAt(i);
        }

        callback( new Blob( [arr], {type: type || 'image/png'} ) );
    }
    });
}
if(!htmlcanvaseelement.prototype.toBlob){
Object.defineProperty(htmlcanvaseElement.prototype,“toBlob”{
值:函数(回调、类型、质量){
var binStr=atob(this.toDataURL(type,quality).split(',')[1]),
len=binStr.长度,
arr=新的UINT8阵列(len);
对于(变量i=0;i
设置功能的大字“不支持”看起来不太好。谢谢,虽然我正在使用的
append
方法有一个红色的
。不确定,但是他们有这两个脚注:[1]在Gecko 7.0(Firefox 7.0/Thunderbird 7.0/SeaMonkey 2.4)之前,如果您指定一个Blob作为要附加到对象的数据,则在“内容配置”中报告的文件名HTTP头是一个空字符串;这导致某些服务器报告错误。从Gecko7.0开始,发送文件名“blob”。[2] Android 4.0中的XHR为带有blob的FormData发送空内容。我假设有些东西是部分兼容的?是的,我正在寻找解决办法,似乎它不完全安全,允许开发人员设置文件输入的值。broswer只允许用户选择文件…你解决了吗?我现在也有同样的问题,我已经被困了好几天了now@user2634633好。。。有点解决了。因此,它指出这是Safari navigator的一个重要安全功能。它不允许程序改变文件输入的内容。安全性背后的想法是,它只允许上传用户自己实际选择的文件。所以我的工作方法是在表单中使用一个普通的文件输入元素,然后从中上传。我决定在上传之前不调整图像大小,但在上传整个文件后在S3服务器上进行了处理。谢谢你提供的信息。最后,我在客户机上进行了裁剪和调整大小,并将数据URI发送到服务器,服务器将其转换为文件并进行S3上传。这有点迂回,但想不出更好的办法了。@user2634633这样,您仍然需要先将文件上传回服务器,对吗?但是我想如果你在客户端调整它的大小,你会在上传回服务器的过程中节省一点,但是你会失去从客户端直接上传到s3所节省的资源。我收回这一点——我刚刚设法让它与Safari的客户端上传一起工作。问题在于我的缩放代码,而不是上传代码。我同步设置了
image.src
,这是一个异步操作,即使与特定的数据URI一起使用也是如此。在Chrome上,这不是问题,但在Safari上,图像高度和宽度设置为0,因为我没有等待图像加载,因此文件大小为0b。检查您的
数据\u url
在Safari和Chrome上是否相同。在使用
image.onload
回调使缩放函数异步后,一切都正常!
if (!HTMLCanvasElement.prototype.toBlob) {
    Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
    value: function (callback, type, quality) {

        var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
            len = binStr.length,
            arr = new Uint8Array(len);

        for (var i = 0; i < len; i++ ) {
        arr[i] = binStr.charCodeAt(i);
        }

        callback( new Blob( [arr], {type: type || 'image/png'} ) );
    }
    });
}