com.ifengxue.http.parser.FilenameInputStream Maven / Gradle / Ivy
/*
* Copyright 2019 https://www.ifengxue.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ifengxue.http.parser;
import com.ifengxue.http.contract.HttpResponse;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
/**
* 带文件名的输入流
*/
public class FilenameInputStream implements AutoCloseable, Closeable {
/**
* 文件名称
*/
private final String filename;
/**
* 输入流
*/
private final InputStream stream;
public static FilenameInputStream from(HttpResponse response) throws IOException {
String headerValue = response.getHeaderValue("Content-Disposition");
String filename = parseAttachmentFilename(headerValue);
return new FilenameInputStream(filename, response.getContent());
}
public FilenameInputStream(String filename, InputStream stream) {
this.filename = filename;
this.stream = stream;
}
public String getFilename() {
return filename;
}
@SuppressWarnings("unused")
public InputStream getStream() {
return stream;
}
@Override
public String toString() {
return "FilenameInputStream{" +
"filename='" + filename + '\'' +
", stream=" + stream +
'}';
}
/**
* 处理附件的文件名。支持RFC 6266标准
*
* Content-Disposition: attachment;filename="encoded_text";filename*=utf-8''encoded_text
*
*/
static String parseAttachmentFilename(String headerValue) throws UnsupportedEncodingException {
if (headerValue == null) {
return null;
}
String filenameWild = "filename*";
int filenameWildIndex = headerValue.indexOf(filenameWild);
if (filenameWildIndex != -1) {
int lastIndex = headerValue.indexOf(';', filenameWildIndex);
String substring;
if (lastIndex == -1) {
substring = headerValue.substring(filenameWildIndex + filenameWild.length() + 1);
} else {
substring = headerValue.substring(filenameWildIndex + filenameWild.length() + 1, lastIndex);
}
String[] ary = substring.split("''");
return URLDecoder.decode(ary[1], ary[0]);
}
String filename = "filename";
int filenameIndex = headerValue.indexOf(filename);
if (filenameIndex != -1) {
int lastIndex = headerValue.indexOf(';', filenameIndex);
String substring;
// 处理filename=文件名,不包含双引号的情况
int offset = 2;
if (headerValue.substring(filenameIndex + filename.length() + 1).charAt(0) != '\"') {
offset = 1;
}
if (lastIndex == -1) {
substring = headerValue.substring(filenameIndex + filename.length() + offset);
} else {
substring = headerValue
.substring(filenameIndex + filename.length() + offset, offset == 2 ? lastIndex - 1 : lastIndex);
}
return URLDecoder.decode(substring, "UTF-8");
}
throw new IllegalStateException("Not valid Content-Disposition header: " + headerValue);
}
@Override
public void close() throws IOException {
if (stream != null) {
stream.close();
}
}
}