2017-01-19 30 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'})); 
    } 
    }); 
} 
相關問題