2012-09-22 13 views
13

iOS6 został zwolniony, a ja testuje przesyłanie zdjęć.iOS6 i Safari Photo Uploading - File API Canvas + jQuery + Ajax Przesyłanie i zmiana rozmiaru plików asynchronicznie

Działa dobrze, ale przy większych obrazach w sieci 3G jest WOLNY zgodnie z oczekiwaniami.

Dzięki interfejsowi API pliku i funkcji Canvas można zmieniać rozmiar obrazów za pomocą JavaScript. Mam nadzieję, że jeśli zmienię rozmiar obrazów, zanim spróbuję je przesłać, będą one szybciej przesyłane - dzięki czemu szybko uzyskasz satysfakcję użytkownika. Ponieważ procesory smartfonów przyspieszają wykładniczo szybciej niż prędkości sieci, uważam, że to rozwiązanie jest zwycięzcą.

Nicolas zaoferował doskonałe rozwiązanie dla zmiany rozmiaru obrazu:

Image resize before upload

Jednak mam najtrudniejszy czas jej realizacji z jQuery AJAX. Wszelkie porady i pomoc są doceniane, ponieważ ten kod będzie prawdopodobnie bardzo przydatny w rozwoju aplikacji mobilnych po IOS6.

var fileType = file.type, 
    reader = new FileReader(); 

reader.onloadend = function() { 
    var image = new Image(); 
    image.src = reader.result; 

    image.onload = function() { 

     //Detect image size 
     var maxWidth = 960, 
      maxHeight = 960, 
      imageWidth = image.width, 
      imageHeight = image.height; 
     if (imageWidth > imageHeight) { 
      if (imageWidth > maxWidth) { 
       imageHeight *= maxWidth/imageWidth; 
       imageWidth = maxWidth; 
      } 
     } else { 
      if (imageHeight > maxHeight) { 
       imageWidth *= maxHeight/imageHeight; 
       imageHeight = maxHeight; 
      } 
     } 

     //Create canvas with new image 
     var canvas = document.createElement('canvas'); 
     canvas.width = imageWidth; 
     canvas.height = imageHeight; 
     var ctx = canvas.getContext("2d"); 
     ctx.drawImage(this, 0, 0, imageWidth, imageHeight); 

     // The resized file ready for upload 
     var finalFile = canvas.toDataURL(fileType); 

     if (formdata) { 

      formdata.append("images[]", finalFile); 

      $.ajax({ 
       url: "upload.php", 
       type: "POST", 
       data: formdata, 
       dataType: 'json', 
       processData: false, 
       contentType: false, 
       success: function (res) { 
        //successful image upload 
       } 
      }); 

     } 
    } 
} 
reader.readAsDataURL(file); 
+0

Znalazłeś rozwiązanie tego? Zauważyłem, że jest to bardziej problematyczne przy zmianie rozmiaru dużych obrazów bezpośrednio z kamery lub zdjęciu z aparatu w przeszłości. – NimmoNet

Odpowiedz

31

Właśnie opracowałem wtyczkę jQuery dla strony klienta zmiana rozmiaru obrazu na płótnie. obsługuje również orientacji a iOS6 zgniecione obraz problem.

Można spróbować: http://gokercebeci.com/dev/canvasresize

Zastosowanie:

$.canvasResize(file, { 
       width : 300, 
       height : 0, 
       crop : false, 
       quality : 80, 
       callback: function(dataURL, width, height){ 

         // your code 

       } 
}); 
+1

to jest fantastyczne. +10 gdybym mógł. Pracuję nad tym od tygodni: – TaylorMac

+0

http://camronjs.herokuapp.com zmiana rozmiaru płótna, websocket i ajax upload safari i przeglądarki. – chrisallick

7

Pracuję z funkcją przesyłania od drugiej wersji beta iOS6. Poniższy kod działa dla mnie:

umieścić to w głowie swojej stronie HTML -

<script>window.onload = function() { 
var canvas = document.createElement('canvas'); 
var ctx = canvas.getContext("2d"); 

var fileSelect = document.getElementById("fileSelect"), 
    input = document.getElementById("input"); 

    input.addEventListener("change", handleFiles); 

    //hides ugly default file input button 
    fileSelect.addEventListener("click", function (e) { 
     if (input) { 
      input.click(); 
     } 
     e.preventDefault(); 
    }, false); 

function handleFiles(e) { 
    var reader = new FileReader; 
    reader.onload = function (event) { 
     var img = new Image(); 
     img.src = reader.result; 
     img.onload = function() { 
      var maxWidth = 320, 
       maxHeight = 350, 
       imageWidth = img.width, 
       imageHeight = img.height; 

      if (imageWidth > imageHeight) { 
       if (imageWidth > maxWidth) { 
        imageHeight *= maxWidth/imageWidth; 
        imageWidth = maxWidth; 
       } 
      } else { 
       if (imageHeight > maxHeight) { 
        imageWidth *= maxHeight/imageHeight; 
        imageHeight = maxHeight; 
       } 
      } 
      canvas.width = imageWidth; 
      canvas.height = imageHeight; 

      ctx.drawImage(this, 0, 0, imageWidth, imageHeight); 

      // The resized file ready for upload 
      var finalFile = canvas.toDataURL("image/png"); 

      var postData = 'canvasData=' + finalFile; 
      var ajax = new XMLHttpRequest(); 
      ajax.open('POST', 'save.php', true); 
      ajax.setRequestHeader('Content-Type', 'canvas/upload'); 

      ajax.onreadystatechange = function() { 
       if (ajax.readyState == 4) { 
        //just to visually confirm it worked... 
        window.open(canvas.toDataURL("image/png"), "mywindow"); 
       } 
      } 
      ajax.send(postData); 
     } 
    } 
    reader.readAsDataURL(e.target.files[0]); 
} 
} 
</script> 

Oto HTML -

<div style="width:320px;position:absolute;z-index:9;top:387px;"> 
<button style="width:60px;" id="fileSelect">upload</button> 
<input type="file" id="input" name="input" accept="image/*" style="display:none;"></div> 

Oto PHP -

<?php 
if (isset($GLOBALS["HTTP_RAW_POST_DATA"])) 
{ 
    // Get the data 
    $imageData=$GLOBALS['HTTP_RAW_POST_DATA']; 

    // Remove the headers (data:,) part. 
    // A real application should use them according to needs such as to check image type 
    $filteredData=substr($imageData, strpos($imageData, ",")+1); 

    // Need to decode before saving since the data we received is already base64 encoded 
    $unencodedData=base64_decode($filteredData); 

    // Save file. This example uses a hard coded filename for testing, 
    // but a real application can specify filename in POST variable 
    $fp = fopen('users/user_photo.png', 'wb'); 
    fwrite($fp, $unencodedData); 
    fclose($fp); 
} 
?> 

Jedynym problemem, z którym walczyłem, jest ładowanie obrazów z aparatu bez obrócenia o 90 stopni.

Nadzieja to pomaga, daj mi znać, jeśli masz jakiekolwiek problemy z kodem (jest to mój pierwszy post).

+0

Fantastyczne. Będę pracował z kodem i zobaczę, czy uda mi się znaleźć rozwiązanie dla obrotu o 90 stopni. Ktoś jeszcze ma na to rozwiązanie? – TaylorMac

+2

Znalazłeś to rozwiązanie do pracy na iPhonie IO6 ze zdjęciami zrobionymi aparatem. Zauważyłem, że wszelkie obrazy, które zostały przeskalowane przy użyciu tej metody, działają, ale obraz jest zgnieciony i nie zgodnie z oczekiwaniami. – NimmoNet

+0

Zobacz tę implementację. To działa dobrze w Chrome na normalnym systemie operacyjnym, ale na IOS podczas zmiany rozmiaru obrazu robi coś dziwnego http://jsfiddle.net/Untd8/ – NimmoNet

1

Biorąc mamy do czynienia z dużymi obrazami i problemów z pamięcią w przeglądarce mobilnej, chciałem zobaczyć, czy to rozwiązanie może lekki można znaleźć, unikając tworzenia duplikatu płótna i wykonywania innych operacji na obrazie tylko w celu wykrycia i zmiany rozmiaru.

Wydaje jeśli Mobile Safari ma pionowo squash obraz, który jest zbyt duży, stosunek o ile to prawda, pozostaje taka sama.

Więc teraz, zanim jeszcze renderować obraz na płótnie, używam bardzo szybki zasada zgodnie z którą po prostu sprawdzić, czy przeglądarka jest mobilnym iDevice navigator.userAgent.match(/(iPod|iPhone|iPad)/) ...I wysokość lub szerokość obrazu jest większa niż 2000 pikseli, w takim przypadku wiem, że zostanie zgnieciony. W tym przypadku, w canvasContext.drawImage() określam wysokość obrazu, która będzie 4 razy wyższa niż normalnie dla danego rozmiaru obrazu. Na podstawie tego, co zobaczyłem, Mobile Safari zgniata obraz czterokrotnie.

THEN renderuję obraz, który po raz pierwszy renderuje się niezniekształcony, przycinając wstępnie rozciągnięty obraz z powrotem do tego, co następnie staje się normalna proporcja X: Y. Bez żadnych dodatkowych elementów canvas lub kontekstów lub renderowania testowe lub iteracje pikselowe, że 100% rozwiązanie wymienione powyżej, używa.

Jestem pewien, że mogą występować przypadki skrajne, a limit rozmiaru obrazu może nie być dokładny, ale dla mojej aplikacji chciałem rozwiązania, które było SZYBKIE.

Powiązane problemy