File upload 如何使用utf-8编码文件名,并在多部分文章中上载文件内容

File upload 如何使用utf-8编码文件名,并在多部分文章中上载文件内容,file-upload,encoding,utf-8,httpurlconnection,multipartform-data,File Upload,Encoding,Utf 8,Httpurlconnection,Multipartform Data,除了文件名为双字节外,上传文件工作正常 下面的代码片段显示了进行文件名编码的可能位置,但不确定它是否正确,或者应用“charset=utf-8”的正确位置在哪里。感谢您的帮助 HttpURLConnection connection = null; DataOutputStream outputStream = null; DataInputStream inputStream = null; String urlString = WebApiConstants

除了文件名为双字节外,上传文件工作正常

下面的代码片段显示了进行文件名编码的可能位置,但不确定它是否正确,或者应用“charset=utf-8”的正确位置在哪里。感谢您的帮助

    HttpURLConnection connection = null;
    DataOutputStream outputStream = null;
    DataInputStream inputStream = null;

    String urlString = WebApiConstants.getInstance().getBaseURL();
    String lineEnd = "\r\n";
    String twoHyphens = "--";
    String boundary = "--BoundaryStringUsingCurrentTime”+currentTimeMillis();

    int bytesRead, bytesAvailable, bufferSize;
    byte[] buffer;
    try {
      URL url = new URL(urlString);
      connection = (HttpURLConnection) url.openConnection();

      connection.setDoInput(true);
      connection.setDoOutput(true);
      connection.setUseCaches(false);

      connection.setRequestMethod("POST");
      connection.setRequestProperty("Connection", "Keep-Alive");

      List<BasicNameValuePair> headers = getHeaderNameValuePairs();

      for (BasicNameValuePair hdr : headers) {
          connection.setRequestProperty(hdr.getName(), hdr.getValue());
      }

      connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
      outputStream = new DataOutputStream(connection.getOutputStream());
      outputStream.writeBytes(twoHyphens + boundary + lineEnd);

      outputStream.writeBytes("Content-Disposition: form-data; name=\"requests\"" + lineEnd);
      outputStream.writeBytes("Content-Type: application/json" + lineEnd + lineEnd);                       
                outputStream.writeBytes(getJsonDataString(attachment.getMessageId()));
                outputStream.writeBytes(lineEnd + twoHyphens + boundary + lineEnd);

      /* ???
      // could encode the fail name and put in, not sure if it is right? 
      String fileNameUtf8 = URLEncoder.encode(fileName, "UTF-8");
      outputStream.writeBytes("Content-Disposition: form-data; name=\"file0\";filename=\""
                   + fileNameUtf8 + "\"" + lineEnd);

      */

      outputStream.writeBytes("Content-Disposition: form-data; name=\"file0\";filename=\""
                   + fileName + "\"" + lineEnd);

      outputStream.writeBytes("Content-Type: " + mimeType + lineEnd + lineEnd);
      FileInputStream fileInputStream = new FileInputStream(new File(pathToFile));
      bytesAvailable = fileInputStream.available();
      bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
      buffer = new byte[bufferSize];

      bytesRead = fileInputStream.read(buffer, 0, bufferSize);
      while (bytesRead > 0) {
        outputStream.write(buffer, 0, bufferSize);
        bytesAvailable = fileInputStream.available();
        bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);
      }

      outputStream.writeBytes(lineEnd);
      outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
                … … …
                … … …
HttpURLConnection=null;
DataOutputStream outputStream=null;
DataInputStream inputStream=null;
字符串urlString=WebApiConstants.getInstance().getBaseURL();
字符串lineEnd=“\r\n”;
字符串双连字符=“--”;
字符串边界=“--BoundaryStringUsingCurrentTime”+currentTimeMillis();
int字节读取,字节可用,缓冲区大小;
字节[]缓冲区;
试一试{
URL=新URL(URL字符串);
connection=(HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(真);
connection.setUseCaches(false);
connection.setRequestMethod(“POST”);
setRequestProperty(“连接”,“保持活动”);
列表标题=getHeaderNameValuePairs();
对于(BasicNameValuePair hdr:Header){
setRequestProperty(hdr.getName(),hdr.getValue());
}
connection.setRequestProperty(“内容类型”、“多部分/表单数据;边界=“+boundary”);
outputStream=新的DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(两个连字符+边界+行结束);
outputStream.writeBytes(“内容处置:表单数据;名称=\“请求\”+lineEnd);
writeBytes(“内容类型:application/json”+lineEnd+lineEnd);
outputStream.writeBytes(getJsonDataString(attachment.getMessageId());
outputStream.writeBytes(lineEnd+两个连字符+边界+lineEnd);
/* ???
//可以对失败名称进行编码并输入,但不确定是否正确?
字符串fileNameUtf8=URLEncoder.encode(文件名为“UTF-8”);
outputStream.writeBytes(“内容处置:表单数据;名称=\“文件0\”文件名=\”
+fileNameUtf8+“\”+lineEnd);
*/
outputStream.writeBytes(“内容处置:表单数据;名称=\“文件0\”文件名=\”
+文件名+“\”+lineEnd);
outputStream.writeBytes(“内容类型:”+mimeType+lineEnd+lineEnd);
FileInputStream FileInputStream=newfileinputstream(新文件(pathToFile));
bytesAvailable=fileInputStream.available();
bufferSize=Math.min(字节可用,最大缓冲区大小);
buffer=新字节[bufferSize];
bytesRead=fileInputStream.read(缓冲区,0,缓冲区大小);
而(字节读取>0){
写入(缓冲区,0,缓冲区大小);
bytesAvailable=fileInputStream.available();
bufferSize=Math.min(字节可用,最大缓冲区大小);
bytesRead=fileInputStream.read(缓冲区,0,缓冲区大小);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(两个连字符+边界+两个连字符+lineEnd);
… … …
… … …

您可以对文件名进行如下编码:

最终私有静态字符串hexStr=“0123456789ABCDEF”;
私有静态字符串MimeEncodeQP(字符串s)
{
字节[]字节=s.getBytes(“UTF-8”);
StringBuilder输出=新的StringBuilder(12+(bytes.length*3));
输出。追加(“=?UTF-8?Q?”);
for(最终字节b:字节)
{
如果(b==32)
{
输出。附加(“”“);
}
如果((b>=33)和&(b=62)和&(b>4)
.append(hexStr.charAt(b&0x0F));
}
}
输出。追加(“?=”);
返回output.toString();
}

outputStream.writeBytes(“内容处置:表单数据;名称=\“file0\”文件名=\”“+MimeEncodeQP(文件名)+“\”“+lineEnd”);
有关详细信息,请阅读以下规格:

,第5.4节“非ASCII字段名”


谢谢雷米。我认为字符串fileNameUtf8=URLEncoder.encode(文件名,“UTF-8”);outputStream.writeBytes(“内容处理:表单数据;名称=\“file0\”;文件名=\”“+fileNameUtf8+“\”“+lineEnd”);更简单,也可以工作。它可能更简单,但在这种情况下,它也是错误的编码方案。
内容处置
是MIME定义的头(请参阅)。我在回答中链接到的各种规范明确指出,文件名需要MIME编码。URL编码使用
%
而不是
=
来表示十六进制值,URL编码使用不同的规则来编码保留字符和空白。因此,不要使用
URLEncoder
来编码文件名。这这不是Web服务器在
多部分/表单数据中所期望的。您自己的问题是“不确定它是否正确”“关于您使用
urlcoder
对文件名进行编码的方式。MIME编码是正确的方式,而不是URL编码。感谢Remy的解释。尝试了您的方式,但在服务器端不起作用。”(但是,如果客户端使用URLEncoder.encode对其进行编码,那么它就可以工作。也许服务器的实现在某种程度上会有所期待?我想知道在发布的数据包的更高级别中是否有一个位置可以指定数据需要utf-8编码,HttpURLConnection如何能够自动处理编码。看起来像li在提交给“内容处置”之前,必须对其进行编码。我展示的是在
内容处置
标题中对文件名进行编码的正确方法。它是一个自包含的标题,没有其他地方可以指定编码。如果服务器不接受它,则服务器已损坏。其解码器有错误,或者它没有首先实现RFC2047。因此,这是服务器端问题。您的客户端必须使用MIME编码,而不是URL编码。句号。这是事实,没有争议。请阅读spe