Spring Boot 对上传文件进行解压缩

起因

在上一篇文章中,简单上手了Spring Boot并进行数据返回,和C#客户端进行数据交互.今天主要是在C#客户端上传文件的时候进行压缩,在服务端解压缩之后,将文件进行保存.

c# 进行Gzip压缩上传

这里主要使用博客园基于HttpContent实现CompressedContent.
public enum CompressionMethod
{
    GZip = 1,
    Deflate = 2
}
public class CompressedContent : HttpContent
{
    private readonly HttpContent _originalContent;
    private readonly CompressionMethod _compressionMethod;

    public CompressedContent(HttpContent content, CompressionMethod compressionMethod)
    {
        if (content == null)
        {
            throw new ArgumentNullException("content");
        }

        _originalContent = content;
        _compressionMethod = compressionMethod;

        foreach (KeyValuePair<string, IEnumerable<string>> header in _originalContent.Headers)
        {
            Headers.TryAddWithoutValidation(header.Key, header.Value);
        }

        Headers.ContentEncoding.Add(_compressionMethod.ToString().ToLowerInvariant());
    }

    protected override bool TryComputeLength(out long length)
    {
        length = -1;
        return false;
    }

    protected async override Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        if (_compressionMethod == CompressionMethod.GZip)
        {
            using (var gzipStream = new GZipStream(stream, CompressionMode.Compress, true))
            {
                await _originalContent.CopyToAsync(gzipStream);
            }
        }
        else if (_compressionMethod == CompressionMethod.Deflate)
        {
            using (var deflateStream = new DeflateStream(stream, CompressionMode.Compress, true))
            {
                await _originalContent.CopyToAsync(deflateStream);
            }
        }
    }
}

使用:

using (HttpClient client = new HttpClient())
{
    string path = Path.Combine(Environment.CurrentDirectory, "vs2019-cpu.png");

    var httpContent = new CompressedContent(new ByteArrayContent(File.ReadAllBytes(path)), CompressionMethod.GZip);

    httpContent.Headers.Add("fileName", "vs2019-cpu.png");

    var requestUri = "http://myabcde.com:8080/uploadFile";
    var result = client.PostAsync(requestUri, httpContent).Result.Content.ReadAsStringAsync().Result;

    Console.WriteLine(result);
}

服务端 Java代码实现

@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public String gzipFile(HttpServletRequest request) throws IOException {

    String contentEncoding = request.getHeader("Content-Encoding");
    if (contentEncoding != null && contentEncoding.indexOf("gzip") > -1) {
        String fileName = request.getHeader("fileName");
        if (fileName != null && fileName != "") {
            fileName = "e:/blog/" + fileName;  //保存文件路径,这样写很不正规,这里只是方便
            ServletInputStream inputStream = request.getInputStream();
            final GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream);
            final int blockSize = 8192;

            byte[] buffer = new byte[blockSize];
            FileOutputStream outputStream = new FileOutputStream(fileName);
            int len;
            while ((len = gzipInputStream.read(buffer, 0, blockSize)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            gzipInputStream.close();
            outputStream.close();
            return "upload ok";
        } else {
            return "fileName is null";
        }
    }

    return "ok";
}

服务端 Owin(c#)实现代码

这里宿主是使用TinyFox(dll版本).
private void DecompressStream(IDictionary<string, object> env)
{
    //获取所有请求头
    var reqHeaders = env["owin.RequestHeaders"] as IDictionary<string, string[]>;
    //获取请求正文
    var reqStream = env["owin.RequestBody"] as Stream;
    if (reqStream != null)
    {
        //获取文件名
        string fileName = reqHeaders["fileName"] != null ? reqHeaders["fileName"][0] : "123.png";
        using (var stream = new MemoryStream())
        {
            //进行解压缩
            using (var gzipStream = new GZipStream(reqStream, CompressionMode.Decompress))
            {
                gzipStream.CopyTo(stream);

                stream.Seek(0, SeekOrigin.Begin);
                byte[] buffer = new byte[stream.Length];
                stream.Read(buffer, 0, (int)stream.Length);
                using (FileStream fileStream = new FileStream(fileName, FileMode.OpenOrCreate))
                {
                    fileStream.Write(buffer, 0, buffer.Length);
                    fileStream.Flush();
                }
            }
        }
    }
}

这里只是简单实现,并没考虑多文件上传,不过看了一下,对文件压缩上传,压缩比例不是很高.

秋风 2020-01-05