我正在尝试使用HttpUrlConnection将图像发送到服务器,因为它是Google推荐的。我决定将图像转换为Base64字符串并将其发送到服务器,我将其解码为.jpg文件。但这种方法只适用于小尺寸缩略图,我无法发送全尺寸图像。
这是android客户端代码:
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服务器代码:
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();
&#13;
我不能对全尺寸图像使用相同的方法,因为BufferedWriter大小限制 - base64编码的字符串太长了。
另一种方法是使用HttpPost和MultipartEntity,但两者都在API22中弃用,我不知道如何处理服务器端的请求。在其他例子中,使用了一些包装器,如两个连字符,边界,crlf,但我找不到原因。
我需要一个HttpUrlConnection的例子
感谢任何帮助,因为我是Android和node.js的新手
答案 0 :(得分:2)
我建议上传二进制数据。您可以将图像元数据(如名称,类型,用户ID,...)作为url参数或自定义http-headers(X -...)放置。
Android客户端代码(未经过测试!):
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,Express代码:
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
和error
事件注册了听众。 data
事件将所有传入的数据块附加到缓冲区。当end
触发时,属性rawBody
将在请求对象中创建,并包含二进制数据(您的图像blob)。 rawBody()
然后将控制转移到下一个处理程序,该处理程序现在可以将blob保存到数据库或文件系统。
在处理非常大的数据blob时,这种处理并不是最好的方法。最好将数据流式传输到文件或数据库以节省内存。
答案 1 :(得分:1)
我还没有足够的分数,所以我必须写一个完整的答案而不是评论。
我想为hgoebl的回答添加一些内容,这很棒,为我节省了很多时间!谢谢!
在您清除流之前,您必须添加这些行,因为没有它们我没有管理它以使其工作。
urlConnection.setRequestProperty("Content-Type", "multipart/form-data");
urlConnection.setFixedLengthStreamingMode(1024);
如果您想直接从USB / SD存储中读取,则无需对Bitmap进行解码并将其编码为压缩格式。只是喜欢
// ... set request header
FileInputStream fis = new FileInputStream(filePath);
OutputStream os = new BufferedOutputStream(urlConnection.getOutputStream());
OutputStreamWriter out = new OutputStreamWriter(os);
byte[] buffer = new byte[1024];
int read;
while ((read = fis.read(buffer)) != -1) {
os.write(buffer, 0, read);
}
... // flush and close
这样你就可以上传任何类型的二进制数据。