最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于HttpClient上傳文件中文名亂碼的解決

 更新時(shí)間:2021年07月01日 09:23:27   作者:風(fēng)再起時(shí)_yhl  
這篇文章主要介紹了HttpClient上傳文件中文名亂碼的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。

現(xiàn)象

使用HttpClient工具上傳文件時(shí),如果文件名是中文,文件名會(huì)亂碼

文件名亂碼的代碼:

private HttpEntity buildEntity(Long scenarioId, List<String> groupIds, String extension,File fileToUpload) {
         MultipartEntityBuilder builder = MultipartEntityBuilder.create();
         builder.addTextBody("scenarioId", scenarioId.toString());
         for (String groupId : groupIds) {
             builder.addTextBody("groupIds", groupId);
         }
         builder.addTextBody("extension", extension);
         builder.addPart("fileToUpload", new FileBody(fileToUpload));
         builder.addTextBody("type", AssetFileTypeEnum.CSV.getName());
         builder.addTextBody("isSplit", "false");
         builder.addTextBody("isRefresh", "false");
         return builder.build();

亂碼原因:

HttpClient上傳文件時(shí),會(huì)調(diào)用doWriteTo方法,寫(xiě)一個(gè)輸出流,但是在調(diào)用formatMultipartHeader方法時(shí),底層主要有3種不同的實(shí)現(xiàn),3種方式的采用的字符集不一樣

HttpClient中的doWriteTo方法:

void doWriteTo(
      final OutputStream out,
      final boolean writeContent) throws IOException {
      final ByteArrayBuffer boundaryEncoded = encode(this.charset, this.boundary);
      for (final FormBodyPart part: getBodyParts()) {
          writeBytes(TWO_DASHES, out);
          writeBytes(boundaryEncoded, out);
          writeBytes(CR_LF, out);
          //此處代碼主要有3種不同的實(shí)現(xiàn),不同的mode,實(shí)現(xiàn)方式不一樣,采用的字符集也不同
          formatMultipartHeader(part, out);
          writeBytes(CR_LF, out);
          if (writeContent) {
              part.getBody().writeTo(out);
          }
          writeBytes(CR_LF, out);
      }
      writeBytes(TWO_DASHES, out);
      writeBytes(boundaryEncoded, out);
      writeBytes(TWO_DASHES, out);
      writeBytes(CR_LF, out);
  }

其中的formatMultipartHeader方法,不同的模式有不同的實(shí)現(xiàn)方式

MultipartEntityBuilder

    MultipartFormEntity buildEntity() {
        String boundaryCopy = boundary;
        if (boundaryCopy == null && contentType != null) {
            boundaryCopy = contentType.getParameter("boundary");
        }
        if (boundaryCopy == null) {
            boundaryCopy = generateBoundary();
        }
        Charset charsetCopy = charset;
        if (charsetCopy == null && contentType != null) {
            charsetCopy = contentType.getCharset();
        }
        final List<NameValuePair> paramsList = new ArrayList<NameValuePair>(2);
        paramsList.add(new BasicNameValuePair("boundary", boundaryCopy));
        if (charsetCopy != null) {
            paramsList.add(new BasicNameValuePair("charset", charsetCopy.name()));
        }
        final NameValuePair[] params = paramsList.toArray(new NameValuePair[paramsList.size()]);
        final ContentType contentTypeCopy = contentType != null ?
                contentType.withParameters(params) :
                ContentType.create("multipart/" + DEFAULT_SUBTYPE, params);
        final List<FormBodyPart> bodyPartsCopy = bodyParts != null ? new ArrayList<FormBodyPart>(bodyParts) :
                Collections.<FormBodyPart>emptyList();
        //此處將mode賦值給modeCopy
        final HttpMultipartMode modeCopy = mode != null ? mode : HttpMultipartMode.STRICT;
        final AbstractMultipartForm form;
        //此處根據(jù)modeCopy的值不同,構(gòu)造3種form,每種的字符集都不一樣,也是產(chǎn)生亂碼的根源
        switch (modeCopy) {
            case BROWSER_COMPATIBLE:
                form = new HttpBrowserCompatibleMultipart(charsetCopy, boundaryCopy, bodyPartsCopy);
                break;
            case RFC6532:
                form = new HttpRFC6532Multipart(charsetCopy, boundaryCopy, bodyPartsCopy);
                break;
            default:
                form = new HttpStrictMultipart(charsetCopy, boundaryCopy, bodyPartsCopy);
        }
        return new MultipartFormEntity(form, contentTypeCopy, form.getTotalLength());
    }
    public HttpEntity build() {
        return buildEntity();
    }

BROWSER_COMPATIBLE模式中的formatMultipartHeader方法

class HttpBrowserCompatibleMultipart extends AbstractMultipartForm {
    private final List<FormBodyPart> parts;
    public HttpBrowserCompatibleMultipart(
            final Charset charset,
            final String boundary,
            final List<FormBodyPart> parts) {
        super(charset, boundary);
        this.parts = parts;
    }
    @Override
    public List<FormBodyPart> getBodyParts() {
        return this.parts;
    }
    /**
      * Write the multipart header fields; depends on the style.
      */
    @Override
    protected void formatMultipartHeader(
            final FormBodyPart part,
            final OutputStream out) throws IOException {
        // For browser-compatible, only write Content-Disposition
        // Use content charset
        final Header header = part.getHeader();
        final MinimalField cd = header.getField(MIME.CONTENT_DISPOSITION);
        //可以看到此處的字符集采用的是設(shè)置的字符集
        writeField(cd, this.charset, out);
        final String filename = part.getBody().getFilename();
        if (filename != null) {
            final MinimalField ct = header.getField(MIME.CONTENT_TYPE);
            //可以看到此處的字符集采用的也是設(shè)置的字符集
            writeField(ct, this.charset, out);
        }
    }
}

RFC6532模式中的formatMultipartHeader方法

class HttpRFC6532Multipart extends AbstractMultipartForm {
    private final List<FormBodyPart> parts;
    public HttpRFC6532Multipart(
            final Charset charset,
            final String boundary,
            final List<FormBodyPart> parts) {
        super(charset, boundary);
        this.parts = parts;
    }
    @Override
    public List<FormBodyPart> getBodyParts() {
        return this.parts;
    }
    @Override
    protected void formatMultipartHeader(
        final FormBodyPart part,
        final OutputStream out) throws IOException {
        // For RFC6532, we output all fields with UTF-8 encoding.
        final Header header = part.getHeader();
        for (final MinimalField field: header) {
            //可以看到此處的字符集默認(rèn)采用UTF8
            writeField(field, MIME.UTF8_CHARSET, out);
        }
    }
}

默認(rèn)模式中的formatMultipartHeader方法

class HttpStrictMultipart extends AbstractMultipartForm {
    private final List<FormBodyPart> parts;
    public HttpStrictMultipart(
            final Charset charset,
            final String boundary,
            final List<FormBodyPart> parts) {
        super(charset, boundary);
        this.parts = parts;
    }
    @Override
    public List<FormBodyPart> getBodyParts() {
        return this.parts;
    }
    @Override
    protected void formatMultipartHeader(
        final FormBodyPart part,
        final OutputStream out) throws IOException {
        // For strict, we output all fields with MIME-standard encoding.
        //從上面注釋中可以看到,此處的字符集采用的是默認(rèn)字符集即ASCII(下面MIME類(lèi)中可以看到)
        final Header header = part.getHeader();
        for (final MinimalField field: header) {
            writeField(field, out);
        }
    }
}

MIME類(lèi)

public final class MIME {
    public static final String CONTENT_TYPE          = "Content-Type";
    public static final String CONTENT_TRANSFER_ENC  = "Content-Transfer-Encoding";
    public static final String CONTENT_DISPOSITION   = "Content-Disposition";
    public static final String ENC_8BIT              = "8bit";
    public static final String ENC_BINARY            = "binary";
    /** The default character set to be used, i.e. "US-ASCII" */
    public static final Charset DEFAULT_CHARSET      = Consts.ASCII;
    /** UTF-8 is used for RFC6532 */
    public static final Charset UTF8_CHARSET         = Consts.UTF_8;
}

解決方法

知道亂碼產(chǎn)生的根源,亂碼問(wèn)題也就好解決了,解決方式有兩種

設(shè)置mode為:BROWSER_COMPATIBLE,并設(shè)置字符集為UTF8

private HttpEntity buildEntity(Long scenarioId, List<String> groupIds, String extension,
                                   File fileToUpload) {
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        //設(shè)置模式為BROWSER_COMPATIBLE,并設(shè)置字符集為UTF8
        builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        builder.setCharset(Charset.forName("UTF-8"));
        builder.addTextBody("scenarioId", scenarioId.toString());
        for (String groupId : groupIds) {
            builder.addTextBody("groupIds", groupId);
        }
        builder.addTextBody("extension", extension);
        builder.addPart("fileToUpload", new FileBody(fileToUpload));
        builder.addTextBody("type", AssetFileTypeEnum.CSV.getName());
        builder.addTextBody("isSplit", "false");
        builder.addTextBody("isRefresh", "false");
        return builder.build();
    }

設(shè)置模式為:RFC6532

    private HttpEntity buildEntity(Long scenarioId, List<String> groupIds, String extension,
                                   File fileToUpload) {
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        //設(shè)置模式為RFC6532
        builder.setMode(HttpMultipartMode.RFC6532);
        builder.addTextBody("scenarioId", scenarioId.toString());
        for (String groupId : groupIds) {
            builder.addTextBody("groupIds", groupId);
        }
        builder.addTextBody("extension", extension);
        builder.addPart("fileToUpload", new FileBody(fileToUpload));
        builder.addTextBody("type", AssetFileTypeEnum.CSV.getName());
        builder.addTextBody("isSplit", "false");
        builder.addTextBody("isRefresh", "false");
        return builder.build();
    }

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java?熱更新?Groovy?實(shí)踐及踩坑指南(推薦)

    Java?熱更新?Groovy?實(shí)踐及踩坑指南(推薦)

    Apache的Groovy是Java平臺(tái)上設(shè)計(jì)的面向?qū)ο缶幊陶Z(yǔ)言,這門(mén)動(dòng)態(tài)語(yǔ)言擁有類(lèi)似Python、Ruby和Smalltalk中的一些特性,可以作為Java平臺(tái)的腳本語(yǔ)言使用,這篇文章主要介紹了Java?熱更新?Groovy?實(shí)踐及踩坑指南,需要的朋友可以參考下
    2022-09-09
  • Java IO流深入理解

    Java IO流深入理解

    這篇文章主要介紹了java IO流的深入理解,下面和小編來(lái)一起學(xué)習(xí)一下吧,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容
    2021-07-07
  • Unity2019-2020 個(gè)人版官方免費(fèi)激活詳細(xì)方法

    Unity2019-2020 個(gè)人版官方免費(fèi)激活詳細(xì)方法

    這篇文章主要介紹了Unity2019-2020 個(gè)人版官方免費(fèi)激活詳細(xì)方法,激活方法分位兩種一種是激活新許可證,一種是手動(dòng)激活,感興趣的朋友跟隨小編一起看看吧
    2021-04-04
  • 關(guān)于Java繼承中父類(lèi)和子類(lèi)構(gòu)造函數(shù)的問(wèn)題

    關(guān)于Java繼承中父類(lèi)和子類(lèi)構(gòu)造函數(shù)的問(wèn)題

    這篇文章主要介紹了關(guān)于Java繼承中父類(lèi)和子類(lèi)構(gòu)造函數(shù)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • Java基于Base64實(shí)現(xiàn)編碼解碼圖片文件

    Java基于Base64實(shí)現(xiàn)編碼解碼圖片文件

    這篇文章主要介紹了Java基于Base64實(shí)現(xiàn)編碼解碼圖片文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • springboot與mybatis整合實(shí)例詳解

    springboot與mybatis整合實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹了springboot與mybatis整合實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • java鏈表數(shù)據(jù)結(jié)構(gòu)LinkedList插入刪除元素時(shí)間復(fù)雜度面試精講

    java鏈表數(shù)據(jù)結(jié)構(gòu)LinkedList插入刪除元素時(shí)間復(fù)雜度面試精講

    這篇文章主要為大家介紹了java LinkedList插入和刪除元素的時(shí)間復(fù)雜度面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 使用?Spring?Boot?Admin?監(jiān)控應(yīng)用狀態(tài)的詳細(xì)過(guò)程

    使用?Spring?Boot?Admin?監(jiān)控應(yīng)用狀態(tài)的詳細(xì)過(guò)程

    這篇文章主要介紹了使用?Spring?Boot?Admin?監(jiān)控應(yīng)用狀態(tài),該模塊采集應(yīng)用的內(nèi)部信息,并暴露給外部的模塊,支持?HTTP?和?JMX,并可以與一些第三方監(jiān)控系統(tǒng)(如?Prometheus)整合,需要的朋友可以參考下
    2022-09-09
  • Spring Data JPA 簡(jiǎn)單查詢--方法定義規(guī)則(詳解)

    Spring Data JPA 簡(jiǎn)單查詢--方法定義規(guī)則(詳解)

    下面小編就為大家?guī)?lái)一篇Spring Data JPA 簡(jiǎn)單查詢--方法定義規(guī)則(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • java字符流緩沖區(qū)詳解

    java字符流緩沖區(qū)詳解

    這篇文章主要為大家詳細(xì)介紹了java字符流緩沖區(qū)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08

最新評(píng)論

大邑县| 武安市| 宁都县| 琼中| 凤庆县| 博白县| 慈利县| 嘉荫县| 房山区| 岑溪市| 玉田县| 年辖:市辖区| 大足县| 松江区| 萨嘎县| 双峰县| 通榆县| 鄢陵县| 治多县| 洮南市| 剑阁县| 朔州市| 宁海县| 葵青区| 喀喇沁旗| 嘉禾县| 凤山市| 丰镇市| 海盐县| 武鸣县| 宜宾县| 息烽县| 江口县| 罗平县| 正宁县| 东明县| 定南县| 九江县| 凭祥市| 通渭县| 江川县|