2

I am creating a cross platform app using PhoneGap and the Intel XDK. I am stuck on how to upload an image from the camera to my Azure Blob Storage. I am generating my SAS without an issue. The problem comes when I try to upload the image itself. I have a URL to the image (localhost) that I want to upload. I first tried to use the file upload utility provided by the XDK like so:

intel.xdk.file.uploadToServer(imageUrl, 
   azureUrl + info.resourceName + '?' + info.sasQueryString, 
   "", 
   "image/jpeg", 
   "updateUploadProgress");

That would start the upload progress (it seemed) and the updateUploadProgress would fire once. If I cut down the image quality and took a picture of just black (smallest size possible), it would get to 100% (otherwise it would get to a smaller percentage) but then nothing. The events that I registered for completion would not fire and I didn't see any error in debugging. My assumption was that it had something to do with the blob type or that it was using a POST instead of a PUT.

I next tried to use a straight XMLHttpRequest. After some configuration, I could get it to upload the output of a canvas object like so:

var canvas = document.createElement("canvas");
var imageObj = document.createElement('img');

imageObj.src = imageUrl;

canvas.width = imageObj.width;
canvas.height = imageObj.height;
var context = canvas.getContext('2d');
context.drawImage(imageObj, 0, 0);

xhr.send(canvas.toDataURL("image/jpeg").split(',')[1]);

The problem there is that it would upload a file of approximately the right size but it was corrupt. This method also doesn't work at all on the iPhone app, just the emulator. I believe there might be an issue using a straight XMLHttpRequest call with the XDK.

Any suggestions for how I can upload this file to Azure?

IAmTimCorey
  • 16,412
  • 5
  • 39
  • 75

1 Answers1

1

Here is working sample code that works for uploading, replace the url with your upload server path, if the upload server is setup to handle correctly, then it will work:

This will only work on real device, either using App Preview or actual built app, does not work in Intel XDK emulator.

<html>
<head>
    <title>intel.xdk.file.uploadToServer</title>
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0;" />  
    <script src="intelxdk.js"></script>
    <script src="xhr.js"></script>
    <script>
function upload(){        
    var url=intel.xdk.webRoot + "somefile.txt";

    intel.xdk.file.uploadToServer(url, "http://www.yourserver.com/upload-handler", "", "text/html", "updateUploadProgress");


    function updateUploadProgress(bytesSent,totalBytes)
    {
       if(totalBytes>0)
            currentProgress=(bytesSent/totalBytes)*100;
       document.getElementById("progress").innerHTML=currentProgress+"%";
    }

    document.addEventListener("intel.xdk.file.upload.busy",uploadBusy);
    document.addEventListener("intel.xdk.file.upload",uploadComplete);
    document.addEventListener("intel.xdk.file.upload.cancel",uploadCancelled);

    function uploadBusy(evt)
    {
       alert("Sorry, a file is already being uploaded");
    }

    function uploadComplete(evt)
    {
       if(evt.success==true)
       {
          alert("File "+evt.localURL+" was uploaded");
       }
       else {
          alert("Error uploading file "+evt.message);
       }
    }

    function uploadCancelled(evt)
    {
        alert("File upload was cancelled "+evt.localURL);
    }   
}    
    </script>
<style>
    body {font-family:arial;background-color:white}
</style>    
</head>
<body>         
    <h3>Upload</h3>
    <button onclick="upload()">upload</button>
    <div id="progress"></div>
</body>
</html>

(I just tested this code, with a server I setup with google app_engine blob store, I setup server on app_engine using this code: Upload files in Google App Engine, if you send me your actual azure url for upload, I can test it too)

Community
  • 1
  • 1
krisrak
  • 12,882
  • 3
  • 32
  • 46
  • Thanks for the help. I really appreciate it. Unfortunately, this doesn't work with Azure. I am uploading from the camera, so I have the full url to the image. However, the URL of the server looks like https://storagename.blob.core.windows.net/container/img101.jpg?{the SAS info}. When I do that using your code, it fires the updateUploadProgress method once and then stops. I think the issue is HTTP PUT and needing to set the equivalent of xhr.setRequestHeader("x-ms-blob-type", "BlockBlob") for the upload. – IAmTimCorey Apr 17 '14 at 19:02
  • what is the URL that handles the upload to azure? – krisrak Apr 17 '14 at 19:05
  • The above is the URL (with my storage name and container name redacted). Instead of going to a web page that processes the file, you send it to "itself" using the above format. I've tested it in Fiddler and it works if I use a PUT. – IAmTimCorey Apr 17 '14 at 19:09
  • can do a console.log of the url and let me know the url, so I can see what the actual url is – krisrak Apr 17 '14 at 20:45
  • Upload links are only valid for five minutes (that is part of the SAS info) but here is a link that was valid a few minutes ago: ht tps://shopsmartapp.blob.core.windows.net/purchaseadvice/photo-06.jpg?se=2014-04-17T22%3A12%3A23Z&sr=b&sp=w&sig=i4aHcoJSYM1DldoPDhHw4myW%2BwF052cpMBx4QLbLqVs%3D (there was a space added in the middle of https to make it not a link) – IAmTimCorey Apr 17 '14 at 22:12
  • why is photo-06.jpg in url? are you trying to upload photo-06.jpg to server? The way intel.xdk.file.uploadToServer works is, you specify the file path in app and upload url of blob server, the url already has a jpg file, not sure what it is for – krisrak Apr 18 '14 at 05:09
  • The image name is in the url because that is what Azure is expecting (for a PUT). I remove it and it does not work still. Like I said, I think the key difference here is that Azure is expecting a PUT and to have the 'x-ms-blob-type' to be set to 'BlockBlob' – IAmTimCorey Apr 18 '14 at 12:35
  • intel.xdk.file.uploadToServer uses POST, this function uses a multi-part POST message to upload the file. – krisrak Apr 18 '14 at 14:04
  • Exactly. If there isn't a way to use this function using a PUT, what are the alternatives? As I said in my question, I tried XMLHttpRequest but that does not seem to work on the device. – IAmTimCorey Apr 18 '14 at 14:18
  • PUT does not work, you have to setup the server to accept POST – krisrak Apr 18 '14 at 23:38
  • Well, I can create a new website to act as a middleman to accept the upload via POST but I would rather not. I don't control the Azure upload method (which is only PUT). That is controlled by Microsoft. Are there any other methods that I can use besides the Intel upload tool to upload files? – IAmTimCorey Apr 19 '14 at 00:57