如何通过HttpUrlConnection将图像从Android客户端发送到Node.js服务器? [英] How to send an image from Android client to Node.js server via HttpUrlConnection?

查看:91
本文介绍了如何通过HttpUrlConnection将图像从Android客户端发送到Node.js服务器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用HttpUrlConnection将图像发送到服务器,因为它是Google推荐的。我决定将图像转换为Base64字符串并将其发送到服务器,我将其解码为.jpg文件。但这种方法只适用于小尺寸缩略图,我无法发送全尺寸图像。

I am trying to send an image to the server using HttpUrlConnection, because it's recommended by Google. I decided to convert the image into Base64 string and send it to the server where I decoded it into .jpg file. But this method is only feasible with small-sized thumbnails and I cannot send a full-sized images.

这是android客户端代码:

Here is the android client code:

 public static void postData(Bitmap imageToSend) {



        try

        {
            URL url = new URL("http://");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");

            conn.setDoInput(true);
            conn.setDoOutput(true);

            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Cache-Control", "no-cache");

            conn.setReadTimeout(35000);
            conn.setConnectTimeout(35000);


            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            // writes a compress version of Bitmap to a specified outputstream
            imageToSend.compress(Bitmap.CompressFormat.JPEG, 100, bos);

            byte[] byteArray = bos.toByteArray();
            String imageEncoded = Base64.encodeToString(byteArray, Base64.DEFAULT);

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("image", imageEncoded));


            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));

            // getQuery is function for creating a URL encoded string
            writer.write(getQuery(params));

            System.out.println("Response Code: " + conn.getResponseCode());

            InputStream in = new BufferedInputStream(conn.getInputStream());
            Log.d("sdfs", "sfsd");
            BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            StringBuilder stringBuilder = new StringBuilder();
            while ((line = responseStreamReader.readLine()) != null)
                stringBuilder.append(line).append("\n");
            responseStreamReader.close();

            String response = stringBuilder.toString();
            System.out.println(response);

            bos.flush();
            bos.close();
            in.close();
            conn.disconnect();

        }

        catch(MalformedURLException e) {
            e.printStackTrace();
        }

        catch(IOException e) {
            e.printStackTrace();
        }


}

Node.js服务器代码:

Node.js server code:

function base64_decode(base64str,file) {
   var bitmap = new Buffer(base64str,'base64');
   //writing into an image file
   fs.writeFile(file, bitmap);
   //write a text file
    console.log('File created from base64 encoded string');
}

app.post("/", function (req,res,next) {
        //requesting the value of the image key which is urlencoded base 64 string
        var image = req.body.image;
        console.log(req.body.image);
        base64_decode(image,'newImage.jpg');

        res.writeHead(200, {'Content-Type':'text/plain'});
        res.write('the image is saved');
        res.end();
        if (req.url != "/")
           next();
 

我不能对全尺寸图像使用相同的方法,因为BufferedWriter大小限制 - base64编码的字符串是它太长了。

I cannot use the same method for the full-sized images, because of the BufferedWriter size limits - the base64 encoded string is too long for it.

另一种方法是使用HttpPost和MultipartEntity,但两者都在API22中被弃用,我不知道如何在服务器端处理请求。其他例子使用了一些包装器,比如两个连字符,边界,crlf,但我找不到原因。

Another method is using HttpPost and MultipartEntity, but both are deprecated in API22, and I did not know how to handle request on the server side. In the other examples some wrappers were used, like two hyphens, boundaries, crlf, but I could not find why.

我需要一个例子使用HttpUrlConnection

I need an example with HttpUrlConnection

感谢任何帮助,因为我是Android的新手和node.js

Any help is appreciated, because I'm newbie to Android and node.js

推荐答案

我建议上传二进制数据。您可以将图像元数据(如名称,类型,用户ID,...)作为url参数或自定义http-headers(X -...)放置。

I'd recommend uploading binary data. You could place image meta-data (like name, type, user-id, ...) as url parameters or custom http-headers (X-...).

Android客户端代码(未经过测试!):

Android client code (not tested!):

 public static void postData(Bitmap imageToSend) {
        try
        {
            URL url = new URL("http://myserver/myapp/upload-image");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");

            conn.setDoInput(true);
            conn.setDoOutput(true);

            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Cache-Control", "no-cache");

            conn.setReadTimeout(35000);
            conn.setConnectTimeout(35000);

            // directly let .compress write binary image data
            // to the output-stream
            OutputStream os = conn.getOutputStream();
            imageToSend.compress(Bitmap.CompressFormat.JPEG, 100, os);
            os.flush();
            os.close();

            System.out.println("Response Code: " + conn.getResponseCode());

            InputStream in = new BufferedInputStream(conn.getInputStream());
            Log.d("sdfs", "sfsd");
            BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            StringBuilder stringBuilder = new StringBuilder();
            while ((line = responseStreamReader.readLine()) != null)
                stringBuilder.append(line).append("\n");
            responseStreamReader.close();

            String response = stringBuilder.toString();
            System.out.println(response);

            conn.disconnect();
        }
        catch(MalformedURLException e) {
            e.printStackTrace();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
}

Node.js,快递代码:

Node.js, Express code:

function rawBody(req, res, next) {
    var chunks = [];

    req.on('data', function(chunk) {
        chunks.push(chunk);
    });

    req.on('end', function() {
        var buffer = Buffer.concat(chunks);

        req.bodyLength = buffer.length;
        req.rawBody = buffer;
        next();
    });

    req.on('error', function (err) {
        console.log(err);
        res.status(500);
    });
}

app.post('/upload-image', rawBody, function (req, res) {

    if (req.rawBody && req.bodyLength > 0) {

        // TODO save image (req.rawBody) somewhere

        // send some content as JSON
        res.send(200, {status: 'OK'});
    } else {
        res.send(500);
    }

});

我将尝试解释node.js部分:
函数 rawBody 充当Express中间件。当发出 POST 请求时,将使用请求对象调用此函数。它为数据结束错误事件注册监听器。 data 事件将所有传入的数据块附加到缓冲区。触发 end 时,会在请求对象中创建属性 rawBody 并包含二进制数据(您的图像blob)。 rawBody()然后将控制转移到下一个处理程序,现在可以将blob保存到数据库或文件系统。

I'll try to explain the node.js part: The function rawBody acts as Express middleware. When a POST request is made, this function gets called with the request object. It registers listeners for data, end and error events. The data events append all incoming chunks of data to a buffer. When end fires, the property rawBody is created in the request object and contains the binary data (your image blob). rawBody() then transfers control to the next handler which can now save the blob to your database or filesystem.

在处理非常大的数据blob时,这种处理不是最好的方法。最好将数据流式传输到文件或数据库以节省内存。

When dealing with really big data blobs, this kind of processing is not the best way. It would be better to stream the data to a file or to the database to save memory.

这篇关于如何通过HttpUrlConnection将图像从Android客户端发送到Node.js服务器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆