2017-01-19 31 views
3

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

我在调试,而blobData在Chrome中的大小为55747,但Safari中只有47560的大小用于同一图像。另外,我还发现了什么看起来略有不同的是,在网络部分开发工具:

铬 - 工作(204响应具有积极大小约534B):

enter image description here

野生动物园 - 不空文件工作(尺寸列显示只是一个虚线)

enter image description here

这里是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'}); 
    } 

我有点不知所措寻找下一个。任何帮助将不胜感激。谢谢!

编辑

只图我应该给多一点信息。 data_url是从一个canvas元素生成的,我用它来调整浏览器中的图像大小,虽然我已经确认canvas在上传之前在safari中正确显示图像。下面是该代码:

function ResizeFile(raw_file) { 

     var reader = new FileReader(); 
     reader.onload = function(e) { 
      var img = document.createElement("img"); 

      img.onload = function() { 

       var canvas = document.createElement('canvas'); 

       var ctx = canvas.getContext("2d"); 
       //ctx.drawImage(img, 0, 0); 

       var MAX = 1200; 
       var width = img.width; 
       var height = img.height; 

       if (width > height) { 
        if (width > MAX) { 
        height *= MAX/width; 
        width = MAX; 
        } 
       } else { 
        if (height > MAX) { 
        width *= MAX/height; 
        height = MAX; 
        } 
       } 
       canvas.width = width; 
       canvas.height = height; 
       ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, width, height); 

       var dataurl = canvas.toDataURL("image/png"); 

       getSignedRequest(dataurl); 

      } 

      img.src = e.target.result; 

     } 
     reader.readAsDataURL(raw_file); 
    } 
+0

你设法解决它之前执行呢?我现在有同样的问题,我一直坚持了几天 – user2634633

+0

@ user2634633以及...有点解决它。所以它称这是Safari浏览器的一个重要安全功能。它不允许程序改变文件输入的内容。安全背后的想法是,它只允许上传用户实际选择的文件。所以我的工作方式是在表单中使用正常的文件输入元素,并从中进行上传。我决定在上传之前不要进行图像大小调整,而是在上传整个文件后在S3服务器上进行处理。 –

+0

感谢您的信息。我最终裁剪并调整了客户端大小,并将数据URI发送到服务器,服务器将其转换为文件并进行S3上传。这有点迂回,但想不到更好。 – user2634633

回答

1
+0

时,我怎么上传thar到s3,'set'函数的大写“不支持”看起来不太好。谢谢,尽管我正在使用'append'方法有一个红色的'?'。 –

+1

不知道,但它们具有那些2个脚注有: [1]之前壁虎7.0(火狐7.0 /雷鸟7.0/SeaMonkey的2.4),如果指定的Blob作为数据附加到对象,在所报告的文件名“Content-Disposition”HTTP头是一个空字符串;这导致一些服务器报告错误。从Gecko 7.0开始,发送文件名“blob”。 [2]在XHR的Android 4.0发送具有斑点为FORMDATA空内容。 我假设像部分合规? – MahdeTo

+0

是的,我正在寻找解决方法,它似乎是不完全安全的,以便开发人员设置文件输入的值。大衣只是让用户选择文件... –

3

我们可以调整图像文件,并上传到服务器。在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'})); 
    } 
    }); 
} 
相关问题