How to stream a String array as a Byte Array over HTTP so that the recipent can create a file out of it at his side?

huangapple go评论62阅读模式
英文:

How to stream a String array as a Byte Array over HTTP so that the recipent can create a file out of it at his side?

问题

以下是您要翻译的内容:

所以,在服务器端我有一个字符串数组,数组中的每个项基本上是最终输出文件中的一行。我不想在服务器端创建这个最终输出文件,而是想将这个字符串数组作为字节数组流传输,以便响应主体可以在客户端写入,并且应该以流式格式创建相应的文件。

我尝试了下面的代码:

String[] convert = MyClass.myMethodWhichGenerateTheStringArray();

final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

objectOutputStream.writeBytes("\n");
for(String s: convert)
{
    objectOutputStream.writeBytes(s + "\n");
}
objectOutputStream.flush();
objectOutputStream.close();

final byte[] byteArray = byteArrayOutputStream.toByteArray();
return request.createResponseBuilder(HttpStatus.OK).body(byteArray).build();

当我读取创建的文件时,我看到一些随机字符,如下所示:

How to stream a String array as a Byte Array over HTTP so that the recipent can create a file out of it at his side?
How to stream a String array as a Byte Array over HTTP so that the recipent can create a file out of it at his side?

在客户端,我只是这样做:

import requests

url = "http://localhost:8081/api/MyFunction"

payload = "{\"fileName\": \"ABCD\", \"fileUrl\": \"https://dahfafj\", \"inputFormat\": \"A\", \"outputFormat\": \"B\"}"
headers = {
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

file = open("resp_text.srt", "wb")
file.write(response.text.encode('utf8'))
file.close()

我的方法正确吗?我应该做什么来修复文件中打印的垃圾字符?

英文:

So I have this string array at the server side, where each item in the array is basically one line in the final output file. I don't want to create this final output file at the server side but instead i would like to stream this string array as a byte array so that the response body can be written at the client side and it should create the respective file in the streamed format.

I have tried the below code:

String[] convert = MyClass.myMethodWhichGenerateTheStringArray();

final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

objectOutputStream.writeBytes("\n");
for(String s: convert)
{
    objectOutputStream.writeBytes(s + "\n");
}
objectOutputStream.flush();
objectOutputStream.close();

final byte[] byteArray = byteArrayOutputStream.toByteArray();
return request.createResponseBuilder(HttpStatus.OK).body(byteArray).build();

I am seeing some random characters when I read the created file as shown below:

How to stream a String array as a Byte Array over HTTP so that the recipent can create a file out of it at his side?
How to stream a String array as a Byte Array over HTTP so that the recipent can create a file out of it at his side?

At the client side all i do is this:

import requests

url = "http://localhost:8081/api/MyFunction"

payload = "{\n    \"fileName\": \"ABCD\",\n    \"fileUrl\": \"https://dahfafj\",\n    \"inputFormat\": \"A\",\n    \"outputFormat\": \"B\"\n}"
headers = {
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data = payload)

file = open("resp_text.srt", "wb")
file.write(response.text.encode('utf8'))
file.close()

Is my approach right? What should I be doing to fix the garbage characters being printed in the file?

答案1

得分: 2

你在这个问题上一团乱。

ObjectOutputStream - 不要使用这个

OOS 和 OIS 主要用于 Java 序列化,你不需要这个(来源:当前负责 Java 的团队非常不喜欢它),这里也不需要。停止使用这个;你不需要使用 OOS 来发送字节数组。这里只需使用普通的 OutputStream

字符集

每当你将字符串转换为字节或反之亦然,都会涉及字符集。如果你不指定一个字符集,你会得到 '平台默认',这是说 '总是完全错误的东西' 的一种委婉说法。所以,在你的测试通过时,当有数百万美元在生产中时,它将失败。始终明确指定你想要的字符集。除非 API 声明总是使用特定的、硬编码的字符集(例如,新的 Files API 将 UTF-8 硬编码,因此那些 '无字符集' 方法如 Files.readAllLines 是可以的。但大多数 Java API 调用将字符转换为字节或反之亦然时,默认使用平台默认字符集,你绝不希望这样)。

请注意,在 Python 方面,你已经吸取了这个教训,并指定了 UTF-8。但在 Java 方面,你没有这样做。

分隔符

你说你想 '发送字符串数组中的每个元素'。你的协议是什么?只是一个接一个地发送字符串,没有办法知道 '下一个' 是什么?你希望在它们之间有一个换行符吗?它应该是 Windows 样式的换行符 (\r\n) 还是 Mac/Unix/网络样式的换行符 (\n)?

从你的代码来看,你似乎想要 \n 作为分隔符。

让我们把它组合起来:

String[] convert = MyClass.myMethodWhichGenerateTheStringArray();

var bytes = new ByteArrayOutputStream();
var out = new OutputStreamWriter(bytes, StandardCharsets.UTF_8);

out.write("\n");
for(String s : convert) {
    out.write(s);
    out.write("\n");
}
out.close();
request.createResponseBuilder(HttpStatus.OK).body(bytes.toByteArray()).build();

或者,稍微重写一些东西以使其更短:

String[] convert = MyClass.myMethodWhichGenerateTheStringArray();
byte[] data = ("\n" + String.join("\n", convert)).getBytes(StandardCharsets.UTF_8);
request.createResponseBuilder(HttpStatus.OK).body(data).build();
英文:

You're all over the place on this.

ObjectOutputStream - don't use this

OOS and OIS are (primarily) for java serialization, which you don't want (SOURCE: The current team in charge of java lament how sucky it is rather a lot), and you don't need here either. Stop using this; you do not need OOS to send byte arrays. Just plain jane OutputStream is all you want here.

charsets

Whenever you convert strings to bytes or vice versa, there is always a charset involved. If you don't specify one, you get 'platform default', which is a nice way of saying 'always exactly the wrong thing'. So, you know - your tests pass, at production time when millions of dollars are on the line, it will fail. Always explicitly specify the charset you wanted. Unless the API says that a specific, hardcoded charset is always used (for example, the new Files API hardcodes UTF-8, so those 'charset less' methods such as Files.readAllLines are okay. But most java API calls that turn chars to bytes or vice versa default to platform default which you never want!).

Note that on the python side you did learn this lesson and are specifying UTF-8. You failed to this on the java side.

Separators

You say you want to 'send each element in the string array'. What is your protocol? Just send one string after another, with zero ways to know when 'the next one in line' is happening? Do you want a newline character in between? Should that be windows style newline (\r\n or mac/unix/network style \n?).

From your code it looks like you want \n separators.

Let's put it together:

String[] convert = MyClass.myMethodWhichGenerateTheStringArray();

var bytes = new ByteArrayOutputStream();
var out = new OutputStreamWriter(bytes, StandardCharsets.UTF_8);

out.write("\n");
for(String s : convert) {
    out.write(s);
    out.write("\n");
}
out.close();
request.createResponseBuilder(HttpStatus.OK).body(bytes.toByteArray()).build();

or, rewriting a few things to make it shorter:

String[] convert = MyClass.myMethodWhichGenerateTheStringArray();
byte[] data = ("\n" + String.join("\n", convert)).getBytes(StandardCharsets.UTF_8);
request.createResponseBuilder(HttpStatus.OK).body(data).build();

huangapple
  • 本文由 发表于 2020年9月7日 22:25:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63779507.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定