Ad

Image Uploading Returns A File Not Found Exception

- 1 answer

I am trying to upload an image from Android client to a .net web API. I can not figure out what's going wrong with the client code.

Client code

@Override
protected String doInBackground(String... strings) {
    try {
        String lineEnd = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";
        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        int maxBufferSize = 1024 * 1024;
        File file = new File(imagePath);

        URL url = new URL(strings[0]);

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Keep-Alive");
        //connection.setRequestProperty("ENCTYPE", "multipart/form-data");
        connection.setRequestProperty("Authorization", "bearer "+ LoginActivity.token);
        connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

        DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());

        Log.d("file path", file.getPath() );

        outputStream.writeBytes(twoHyphens + boundary + lineEnd);
        //outputStream.writeBytes(lineEnd);
        outputStream.writeBytes("Content-Disposition: form-data; name=\"ProfilePic\"; filename=\""+ file.getAbsolutePath() + "\"" + lineEnd);
        outputStream.writeBytes("Content-Type: image/png" + lineEnd);

        FileInputStream fileInputStream;
        fileInputStream = new FileInputStream(file.getAbsoluteFile());
        bytesAvailable = fileInputStream.available();
        bufferSize = Math.min(bytesAvailable, maxBufferSize);
        buffer = new byte[bufferSize];

        // Read file
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);

        while (bytesRead > 0) {
            try{
                outputStream.write(buffer, 0, bufferSize);
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
                Log.d("Exception occured", "Out of memory");
                return "out of memory";
            }
            bytesAvailable = fileInputStream.available();
            Log.d("output stream", outputStream+"");
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        }
        outputStream.writeBytes(lineEnd);
        outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

        Log.d("Response image upload", connection.getResponseCode()+"");

        /*** output printing ***/
        BufferedReader _reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String line = "";
        StringBuilder response = new StringBuilder();

        while( (line = _reader.readLine()) != null ) {
            response.append(line);
        }

        String data = response.toString();

        Log.d("Output data", data);
        /****/

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Server code

[HttpPost]
public IHttpActionResult SaveImage()
{
 var httpRequest = HttpContext.Current.Request;
 HttpPostedFile file = httpRequest.Files["ProfilePic"];

 if (file == null)
   throw new EmptyObjectException(ErrorMessageTypes.EmptyObject, jobSeekerId);

 // saving the image
}

What actually is happening is- somehow the image is not being sent properly from client. It would be great to have your help on this context. Thanks

Ad

Answer

I've found the solution. Android HttpUrlConnection is a bit restricted for file uploading sort of things. It has a specific format- if violated it won't work. The format is

--xxxxxxxxxx
Content-Disposition: form-data; name="filetoupload"; filename="helloworld.png"
Content-Type: image/png

Image data 
--xxxxxxxxxx--

here 'xxxxxx' part is the one we call boundary. '--' is twoHyphens. And the lineEnd must be put in the right place with right amount. So in my code it should be

outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"ProfilePic\"; filename=\""+ file.getPath() + "\"" + lineEnd);
outputStream.writeBytes("Content-Type: image/png" + lineEnd);
outputStream.writeBytes(lineEnd);

FileInputStream fileInputStream;
fileInputStream = new FileInputStream(file.getPath());
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];

// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0) {
    try{
        outputStream.write(buffer, 0, bufferSize);
    } catch (OutOfMemoryError e) {
        e.printStackTrace();
        Log.d("Exception occured", "Out of memory");
        return "out of memory";
    }
    bytesAvailable = fileInputStream.available();
    bufferSize = Math.min(bytesAvailable, maxBufferSize);
    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

I am grateful to this blog

Ad
source: stackoverflow.com
Ad