JAVA小工具-05-HttpClient/PostMethod上传文件(解决中文文件名乱码问题)

言于头:本节讨论的是在项目中利用HttpClient/PostMethod相关api进行上传文件操作时,会出现上传中文文件名乱码问题。为解决这个问题,下面是总结的一个HTTP工具类以及测试用例。

public class HttpUtils {
    public static final String UTF_8 = "UTF-8";
    private static final  Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
    private static MultiThreadedHttpConnectionManager connectionManager = null;
    private static int connectionTimeOut = 60000;
    private static int socketTimeOut = 60000;
    private static int maxConnectionPerHost = 20;
    private static int maxTotalConnections = 20;
    private static HttpClient client;
    static {
        connectionManager = new MultiThreadedHttpConnectionManager();
        connectionManager.getParams().setConnectionTimeout(connectionTimeOut);
        connectionManager.getParams().setSoTimeout(socketTimeOut);
        connectionManager.getParams().setDefaultMaxConnectionsPerHost(maxConnectionPerHost);
        connectionManager.getParams().setMaxTotalConnections(maxTotalConnections);
        client = new HttpClient(connectionManager);
        client = new HttpClient(connectionManager);
    }
	/*  *
     * @description:  上传一个文件
     * url :请求路径
     * file: 上传的文件
     * parmas:其他表单参数
     **/
    public static String sendFileRequest(String url, File file,Map<String,String> parmas) {
        String response = "";
        PostMethod postMethod = null;
        // 自定义header:如果需要的话
        Map headers=new HashMap();
        try {
            postMethod = new PostMethod(url){
                @Override
                public String getRequestCharSet() {
                    return "UTF-8";
                }
            };
            // 填入header:如果需要的话
            if (headers != null && headers.size() > 0) {
                Iterator var5 = headers.entrySet().iterator();
                while(var5.hasNext()) {
                    Map.Entry entry = (Map.Entry)var5.next();
                    postMethod.setRequestHeader(entry.getKey().toString(), entry.getValue().toString());
                }
            }
            //填入其他表单参数
            Integer len=parmas.size()+1;
            Part[] parts=new Part[len];
            Integer indx=0;
            for (Map.Entry<String, String> stringStringEntry : parmas.entrySet()) {
                postMethod.setParameter(stringStringEntry.getKey(),stringStringEntry.getValue());
                StringPart stringPart=new StringPart(stringStringEntry.getKey(),stringStringEntry.getValue());
                parts[indx]=stringPart;
                indx++;
            }
            // 自定义文件解析器(解决中文文件乱码),需要注意的是其中 file:对应的是被调用接口中的file 参数
            CustomFilePart filePart = new CustomFilePart("file", file);
            parts[parmas.size()]=filePart;
            postMethod.setRequestEntity(new MultipartRequestEntity(parts,postMethod.getParams()));
            int statusCode = client.executeMethod(postMethod);
            if (statusCode == 200) {
                response = convertStreamToString(postMethod.getResponseBodyAsStream());
            } else {
                LOGGER.error("响应状态码 = " + postMethod.getStatusCode()
                        +";响应状态信息 = "+postMethod.getStatusText()+"响应体信息 = "+ postMethod.getResponseBodyAsString());
            }
        } catch (HttpException var11) {
            LOGGER.error("发生致命的异常,可能是协议不对或者返回的内容有问题", var11);
        } catch (IOException var12) {
            LOGGER.error("发生网络异常", var12);
        } finally {
            if (postMethod != null) {
                postMethod.releaseConnection();
            }
        }
        return response;
    }

    /**
     * 输入流转字符串
     * @param inputStream 输入流
     * @return 返回结果
     * @throws IOException IO异常
     */
    private static String convertStreamToString(InputStream inputStream) throws IOException {
        String result = "";
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[Constant.Numberic.N_1024];
        int len;
        // 将输入流转移到内存输入流中
        try {
            while ((len = inputStream.read(buffer, Constant.Numberic.N_0, buffer.length)) != Constant.Numberic.NEGATIVE_ONE) {
                out.write(buffer, Constant.Numberic.N_0, len);
            }
            // 将内存流转换成字符串
            result = new String(out.toByteArray(),"UTF-8");
        } catch (IOException e) {
            LOGGER.error("convertStreamToString发生异常",e);
        } finally {
            out.close();
        }
        return result;
    }
}

自定义的文件接收器CustomFilePart 继承FilePart :

public class CustomFilePart extends FilePart {

    public CustomFilePart(String name, File file) throws FileNotFoundException {
        super(name, file);
    }

    @Override
    protected void sendDispositionHeader(OutputStream out) throws IOException {
        //super.sendDispositionHeader(out);
        //下面部分其实为实现父类super.sendDispositionHeader(out) 里面的逻辑
        out.write(CONTENT_DISPOSITION_BYTES);
        out.write(QUOTE_BYTES);
        out.write(EncodingUtil.getBytes(getName(),"utf-8"));
        out.write(QUOTE_BYTES);
        String fileName = getSource().getFileName();
        // 此处为解决中文文件名乱码部分
        if (!StringUtils.isEmpty(fileName)){
            out.write(EncodingUtil.getAsciiBytes(FILE_NAME));
            out.write(QUOTE_BYTES);
            out.write(EncodingUtil.getBytes(fileName,"utf-8"));
            out.write(QUOTE_BYTES);
        }
    }
}

如下为一个测试用例,过程:
1、先在Controller中编写两个普通的上传文件接口。
2、在其中一个A上传接口中利用上面编写的http调用另外一个B上传接口,并在B接口中打印输出查看效果。
实现如下:

@Controller
@RequestMapping(value = "/test/api/v1")
public class TestController {
    private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);
	/**
	* A上传接口,用于web端调用,此处使用postman测试
	**/
    @RequestMapping("/import/file")
    @ResponseBody
    public Response uploadFile(@RequestParam("file") MultipartFile uploadFile, String objType, String createUser) {
        try {
            Map parma=new HashMap();
            parma.put("objType",objType);
            parma.put("createUser",createUser);
            // 此处url为下面的B上传接口
            String url="http://15.*******:***/test/api/v1/import/file/http";
            return Response.ok(HttpUtils.sendFileRequest(url,mutilFile2File(uploadFile),parma));
        }catch (Exception e){
            LOGGER.error("上传数据文件异常",e);
            return Response.error("获取uploadFile失败!"+e.getMessage());
        }
    }
	/**
	* B上传接口,直接打印输出
	**/
    @RequestMapping("/import/file/http")
    @ResponseBody
    public Response uploadFileHttp(@RequestParam("file") MultipartFile uploadFile, Integer objType, String createUser) {
        try {
            LOGGER.info("fileName:"+uploadFile.getOriginalFilename()+";objType:"+objType+";createUser:"+createUser);
            return Response.ok(uploadFile.getOriginalFilename());
        }catch (Exception e){
            LOGGER.error("上传数据文件异常uploadFileHttp",e);
            return Response.error("获取uploadFileHttp失败!"+e.getMessage());
        }
    }
	/**
	* 将web端上传的MultipartFile 转换成普通的File
	**/
    public File mutilFile2File(MultipartFile multipartFile){
        File file=null;
        try {
            File destFile = new File("/upload/data/");
            if (!destFile.exists()) {
                destFile.mkdirs();
            }
            //将文件存储到本地
            String fileName=new String(multipartFile.getOriginalFilename().getBytes("utf-8"));
            file = new File(destFile.getAbsolutePath() + "/" + fileName);
            multipartFile.transferTo(file);
            file.createNewFile();
        }catch (Exception e){
            LOGGER.error("mutilFile2File异常:",e);
        }finally {
            return file;
        }
    }
}

postman调用如下:
在这里插入图片描述

B上传接口输出:
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值